Por que o OpenGL> = 3 permite apenas VBOs?

21

Vejo que o OpenGL versões 3 e posteriores eliminam o uso da renderização do lado do cliente. O modo imediato foi eliminado e as matrizes de vértices parecem obsoletas. Em vez disso, se bem entendi, os VBOs são a principal maneira de renderizar vértices.

Embora eu veja a lógica por trás de ter uma maneira uniforme de renderizar tudo, será que os VBOs não têm grandes desvantagens em relação às matrizes de vértices? Eu pensei que os VBOs deveriam ser grandes buffers contendo> 1 MB de dados, geralmente. E se eu tiver uma cena com uma geometria menor? Eu tenho um gráfico de cena com um grande número de nós, cada um dos quais precisa de sua própria transformação etc. Cada nó também deve poder ser excluído separadamente, adicionado a separadamente etc. Eu estava usando matrizes de vértices antes. Portanto, minha primeira pergunta é se, se eu mudar para VBOs, haverá uma sobrecarga maior nos meus objetos de gráfico de cena agora porque um VBO precisa ser alocado para cada objeto.

Outra preocupação é que a geometria que estou renderizando pode ser altamente dinâmica. Na pior das hipóteses, pode haver momentos em que toda a geometria precise ser reenviada a cada quadro por algum período de tempo. As VBOs terão desempenho pior do que as matrizes de vértices nesse caso de uso ou as VBOs, na pior das hipóteses, funcionam tanto quanto as matrizes de vértices, mas não mais?

Então, em um formato mais conciso, minhas perguntas são:

1) Existe uma sobrecarga substancial na alocação / desalocação de VBOs (quero dizer o mero ato de configurar um buffer)?

2) Se estou atualizando os dados da CPU a cada quadro, isso pode ser substancialmente pior do que se eu tivesse usado matrizes de vértices?

E, finalmente, eu gostaria de saber:

3) Se a resposta para qualquer uma das perguntas acima for "sim", por que reprovar outros modos de renderização que podem ter vantagens sobre os VBOs? Há algo que estou faltando aqui, como técnicas que devo usar para mitigar alguns desses custos de alocação em potencial etc.?

4) As respostas para qualquer uma dessas perguntas mudam substancialmente dependendo da versão do OpenGL que estou usando? Se eu refatorar meu código para que seja compatível com o OpenGL 3 ou 4 usando VBOs de uma maneira que seja de bom desempenho, as mesmas técnicas provavelmente terão um bom desempenho com o OpenGL 2 ou será provável que certas técnicas sejam muito mais rápidas com o OpenGL 3 + e outros com OpenGL 2?

Fiz essa pergunta no estouro de pilha, mas estou postando novamente aqui porque percebi que este site pode ser mais apropriado para minha pergunta.

Gravidade
fonte
1
Por que uma votação para fechar? É um idiota? Em caso afirmativo, posso ver um link para poder me beneficiar dele?
Gravity

Respostas:

23

Existe uma sobrecarga substancial na alocação / desalocação de VBOs (quero dizer o mero ato de configurar um buffer)?

Defina "substancial". É geralmente prudente não criá-los no meio dos quadros; eles devem ser configurados durante a inicialização ou em qualquer outro lugar. Mas isso é verdade para a maioria dos objetos OpenGL, como texturas, buffers de renderização ou shaders.

Se estou atualizando os dados da CPU a cada quadro, isso pode ser substancialmente pior do que se eu tivesse usado matrizes de vértices?

Pode? Sim. O OpenGL define funcionalidade, não desempenho . Você pode realmente tornar as coisas muito mais lentas. Ou você pode tornar as coisas mais rápidas. Tudo depende de como você o usa.

O OpenGL Wiki tem um bom artigo sobre como transmitir dados corretamente .

Se a resposta para qualquer uma das perguntas acima for "sim", por que reprovar outros modos de renderização que podem ter vantagens sobre os VBOs? Há algo que estou faltando aqui, como técnicas que devo usar para mitigar alguns desses custos de alocação em potencial etc.?

Primeiro, eles não foram apenas preteridos. Reprovação significa marcar algo como "a ser removido" em versões futuras. Eles foram descontinuados no 3.0 e removidos no núcleo 3.1 e acima.

Segundo, o ARB geralmente explicou o motivo pelo qual removeu coisas do OpenGL. Isso torna as especificações menores e mais simples. Isso torna a API menor e mais simplificada. Torna mais fácil saber quais APIs você deve usar; 2.1 tinha 4 maneiras de fornecer dados de vértice; 3.1+ tem 1. Ele se livra de muita sujeira. Etc.

As respostas para alguma dessas perguntas mudam substancialmente dependendo da versão do OpenGL que estou usando? Se eu refatorar meu código para que seja compatível com o OpenGL 3 ou 4 usando VBOs de uma maneira que seja de bom desempenho, as mesmas técnicas provavelmente terão um bom desempenho com o OpenGL 2 ou será provável que certas técnicas sejam muito mais rápidas com o OpenGL 3 + e outros com OpenGL 2?

Mais ou menos não. Somente no MacOSX a diferença entre as versões 3.1 + core e pré-3.0 é realmente aparente. O perfil de compatibilidade é implementado por todos os drivers para Linux e Windows, portanto, você pode assumir que o perfil principal desses drivers está apenas adicionando verificações para impedir que você chame as funções de compatibilidade.

No Mac OSX 10.7, o núcleo GL 3.2 está disponível, mas não o perfil de compatibilidade. Isso não significa necessariamente nada para as técnicas de desempenho, uma contra a outra. Mas isso significa que, se houver diferenças, é nessa plataforma que você as verá.

Nicol Bolas
fonte
1
Como você acabou de postar esta pergunta em cruz, postarei minha resposta em cruz.
Nicol Bolas
Outra vantagem de manter a API concisa é que ela facilita a implementação da API OpenGL. Essa foi uma grande consideração na especificação original do OpenGL ES.
notlesh
@stephelton: faz sentido. Minha pergunta "por que depreciar tudo, menos os VBOs" foi baseada no pensamento de que, embora faça todo o sentido manter a API enxuta, não faz sentido depreciar recursos que poderiam ser melhores que os VBOs para muitos casos de uso. Pelo que estou ouvindo, parece que não há desvantagens no uso de VBOs; portanto, faz todo o sentido depreciar todo o resto.
Gravity
@ Gravity Você não precisa usar VBO's. Você também pode usar uma matriz de vértices.
notlesh
18

Da maneira que o OpenGL funciona, sempre que você usa dados que não sejam da VBO, o driver precisa fazer uma cópia - na prática, criando uma VBO temporária - já que nada impede você de modificar suas matrizes nuas no espaço do usuário entre as chamadas para o OpenGL.

Pode haver alguns truques do lado do motorista para acelerar a alocação temporária, mas não há nada que você possa fazer para evitar a cópia.

Então sim, contanto que você - e os desenvolvedores do driver - façam tudo certo, os VBOs devem (tm) sempre apenas acelerar as coisas.

Jari Komppa
fonte
6
Eu gosto mais desta resposta. É mais curto e mais direto ao ponto, imo.
TravisG
@JariKomppa: Isso soa como uma explicação bastante razoável. Ainda tenho uma preocupação: os VBOs devem ser objetos razoavelmente grandes, geralmente alocados como buffers de 1 MB a 4 MB na última vez que verifiquei. E se meus objetos de geometria não forem tão grandes, mas ainda estou preocupado com o desempenho porque tenho muitos objetos? Estou preocupado que os VBOs possam ser apenas para um caso de uso diferente do que eu tenho. Devo agrupar vários objetos juntos em um único VBO e depois usar glDrawRangeElementspara desenhar cada objeto individual, ou isso é ineficiente como as matrizes de vértices?
Gravity
Duvido que isso faça alguma diferença, mas se você sentir que é uma preocupação, faça um benchmark.
Jari Komppa
@JariKomppa: O que você duvida que fará a diferença? Usando glDrawRangeElementsvárias vezes em cada VBO com alguns VBOs, em vez de dar a cada objeto seu próprio VBO?
Gravity
1
Exatamente. Duvido que você veja muita diferença lá, mas a criação de perfis de alguns casos de teste deve fornecer mais informações. Eu também não me preocuparia com isso agora, pois uma mudança como essa poderia ser aplicada mais tarde, se necessário.
Jari Komppa
9

e matrizes de vértices parecem obsoletas. Em vez disso, se eu entendi direito,

Não é bem assim. Matrizes de vértice são a base para objetos de buffer de vértice. Somente o armazenamento mudou do cliente para o servidor.

E se eu tiver uma cena com uma geometria menor?

Mesclar conjuntos de geometria menores em VBOs maiores. Não é necessário ter um VBO por lote de geometria. Você pode endereçar perfeitamente subconjuntos de um VBO para renderização. Use um deslocamento diferente de zero para o parâmetro gl… Pointer data.

2) Se estou atualizando os dados da CPU a cada quadro, isso pode ser substancialmente pior do que se eu tivesse usado matrizes de vértices?

Para isso, existem os sinalizadores de uso do buffer GL_DYNAMIC_DRAW e GL_STREAM_DRAW.

Se a resposta para qualquer uma das perguntas acima for "sim", por que reprovar outros modos de renderização que podem ter vantagens sobre os VBOs?

Porque não há vantagens. Os dados da geometria devem ser transferidos para a GPU em qualquer caso. O uso de uma matriz regular de vértices do lado do cliente ainda causará uma transferência de DMA para a GPU, e o modo imediato criará um lote para transferir primeiro também.

Não há absolutamente nenhum benefício em não usar VBOs.

datenwolf
fonte
Portanto, meu desempenho geralmente não deve ser pior com VBOs do que com matrizes de vértices, mas apenas se eu definir corretamente o modo como GL_STREAM_DRAW?
Gravity
@ Gravity: De fato. No entanto, o modo de buffer é apenas uma dica sobre o uso esperado, mas é claro que essa dica deve ser verdadeira para o que você fará. Além disso, não esqueça que você pode mapear buffers no espaço de endereço do processo para atualizações (glMapBuffer, glUnmapBuffer).
datenwolf
mas o buffer não pode estar na VRAM, certo? Ou ainda estaria na VRAM, mas apenas endereçável através de endereços de espaço de processo? O acesso aleatório seria barato com essa técnica ou ainda devo tentar atualizar apenas um pequeno número de intervalos contíguos?
Gravity
@ Gravity: um buffer pode ser mapeado somente leitura, somente gravação ou leitura e gravação. Para atualizações, você escolheria somente gravação. Agora, é importante saber como o sistema operacional moderno gerencia o espaço de endereço virtual, principalmente através da memória paginada. No caso de um mapa somente de gravação, você mapeará uma parte da memória de transferência DMA e suas gravações nesse intervalo mapeado irão para a memória da GPU mais ou menos diretamente (o conteúdo é gravado primeiro na RAM da CPU, mas depois transferido para a GPU pela DMA transferir). É importante que este é um caminho mais direto do que se os dados passa por uma matriz cliente lado vértice: memória do processo regular não está apto para DMA
datenwolf