A modificação de uma textura (pintura sobre ela) é considerada uma "mudança de estado"?

11

A convenção nos gráficos é que realizar menos alterações de estado é melhor do que realizar mais alterações de estado (comutadores de sombreamento, buffers de ligação, texturas de ligação etc.). Para texturas, é mais rápido renderizar muitos polígonos usando um único atlas (para renderizar sprites / texto) do que vincular individualmente uma nova textura para cada polígono.

Isso se aplica se eu estiver continuamente pintando em uma textura glTexSubImage2D? Eu tenho um fluxo de dados entrando (por uma rede) que passa por processamento e é pintado em uma textura de uma linha por vez. Os dados são apresentados visualmente em um rolo sem fim.

Seria melhor pintar em uma textura renderizada em um retângulo grande (rolando os dados pintados para exibição)? A idéia aqui é que eu teria uma (ou duas) texturas vinculadas a qualquer momento, enquanto continuo pintando.

Ou devo pintar muitos pequenos retângulos (apenas revelando o retângulo quando a pintura é concluída)? Suponho que vincularia uma textura por retângulo.

TheBuzzSaw
fonte

Respostas:

11

Atualizar uma área de memória no dispositivo gráfico (uma textura, buffer e similares) não é o mesmo que alterar um estado de renderização.

O que torna uma alteração de estado de renderização cara é a quantidade de trabalho que o motorista precisa realizar para validar o (s) novo (s) estado (s) e reordenar o pipeline. Provavelmente, também ocorrerá alguma sincronização entre a CPU e o dispositivo gráfico. No entanto, a quantidade de dados transferidos entre os dispositivos deve ser pequena para uma alteração de estado (provavelmente apenas alguns comandos).

Por outro lado, para uma atualização de textura / buffer, o principal custo está na própria transferência de dados. Em teoria, a menos que você esteja lendo os dados de textura de volta para a CPU após a atualização, não haverá sincronização ou paralisação de pipeline. No entanto, outro aspecto deve ser considerado: sobrecarga da API. Mesmo que a quantidade de dados que você está enviando para o dispositivo gráfico seja pequena, se você fizer isso com bastante frequência, eventualmente o custo da comunicação com o driver / dispositivo se tornará maior que o custo da transferência de dados. Essa é outra razão pela qual o lote é tão importante ao otimizar um renderizador.

Portanto, no meu caso, a melhor abordagem, parece-me, seria manter uma cópia na memória do sistema da textura que você atualiza sempre que novos dados chegam. Defina um sinalizador sujo e consolide o máximo de atualizações possível em um glTexSubImagepara toda a textura (ou uma grande parte seqüencial). Você também pode jogar com o Pixel Buffer Objects e tentar fazer a transferência de dados assíncrona para reduzir ao máximo as paradas do pipeline. Se você pode implementar algum tipo de buffer duplo, pode gravar em uma cópia da textura enquanto a outra está sendo renderizada. Este tutorialexplora esse cenário. Essa é a minha abordagem intuitiva, tentaria reduzir o número de chamadas de API e "agrupar" as atualizações de textura. Dito isto, isso é muito especulativo, e você teria que criar um perfil e compará-lo a outras abordagens, como fazer várias pequenas atualizações, para ter certeza de qual é o melhor desempenho no seu caso de uso.

Como uma observação lateral, esta apresentação da NVidia também é relevante e fornece muitos insights: Abordando a sobrecarga de driver zero no OpenGL .

glampert
fonte
5
Não sei ao certo, mas definitivamente suspeitaria que glTexSubImage em uma textura que foi renderizada no último quadro ou dois paralisará o pipeline, já que os drivers de PC geralmente tentam armazenar um ou dois quadros e não são prováveis querer fazer cópias de texturas inteiras por causa de uma pequena atualização. Portanto, eu esperava que o buffer duplo ou triplo das texturas (ou objetos de buffer de pixel) fosse necessário para obter o desempenho máximo.
John Calsbeek