Como sei se estou abstraindo APIs de gráficos com muita força?

23

Ao criar um renderizador que oferece suporte a várias APIs gráficas, você normalmente deseja abstrair seu código em algum tipo de biblioteca de baixo nível associada a alguma API gráfica, como OpenGL, Vulkan, D3D11 e assim por diante;

Eles funcionam de maneira muito diferente um do outro, tornando essencial uma boa API genérica; Eu li que você normalmente gostaria de usar um "back-end" que implementa a funcionalidade básica de cada API que você deseja oferecer suporte e um "front-end" que é usado pelo programador para desenhar coisas no tela.

Como sei se estou fazendo uma abstração muito rígida?

Gabriele Vierti
fonte
5
Você tem 100% de certeza de que seu wrapper + Vulkan ou D3D11 é mais rápido do que sempre usando o OpenGL?
Mooing Duck
@ Duck Mooing, se usado corretamente, sim.
Gabriele Vierti
4
Eu duvido seriamente disso. A maioria dos ganhos no Vulkan vem de um nível muito baixo e de fazer as coisas de uma maneira muito peculiar e específica. Algo que é genérico o suficiente para fazer o mesmo perfeitamente no OpenGL ou D3D quase certamente não pode fazer isso. Reimplementar o mesmo material que o OpenGL (como muitos tutoriais da Vulkan fazem, ironicamente) resulta em 99,99% do mesmo desempenho, com 20 vezes o trabalho.
Damon
@ Damon está certo, mas as APIs mais recentes são projetadas especificamente (e não adaptadas como o OpenGL) para funcionar nos gpus modernos; falando do Vulkan, você pode usar praticamente a mesma API em todas as plataformas suportadas, ao contrário do OpenGL, onde você precisa usar a versão "Embedded Systems". Outros que menos sobrecarga de CPU e fantasia características não temos muito, mas no futuro poderemos ter algumas técnicas muito surpreendentes que podem correr mais rápido usando Vk ou D3D12 em vez de OGL ou D3D11
Gabriele Vierti

Respostas:

44

Primeiro, considere se realmente vale a pena oferecer suporte a mais de uma API de gráficos. O simples uso do OpenGL cobrirá a maioria das plataformas e será "bom o suficiente" para todos os projetos, exceto os mais ambiciosos em termos gráficos. A menos que você trabalhe em um estúdio de jogos muito grande, que pode gastar milhares de horas-pessoa para implementar e testar vários back-ends de renderização e, a menos que haja alguns recursos específicos do DirectX ou Vulcan que você realmente queira exibir, geralmente não vale a pena o aborrecimento . Especialmente considerando que você pode economizar muito trabalho usando uma camada de abstração criada por outra pessoa (uma biblioteca de terceiros ou um mecanismo de jogo).

Mas vamos supor que você já tenha avaliado suas opções e chegou à conclusão de que é viável e vale o tempo necessário para criar as suas.

Então, o juiz principal da arquitetura de software da sua camada de abstração são seus programadores front-end.

  • Eles são capazes de implementar os sistemas de jogos que desejam implementar sem ter que se perguntar sobre detalhes de baixo nível?
  • Eles conseguem ignorar completamente a existência de mais de uma API gráfica?
  • Teoricamente, seria possível adicionar mais um backend de renderização sem alterar o código do front-end?

Se sim, você conseguiu.

Philipp
fonte
2
Uma sugestão adicional: vale a pena enfatizar que o objetivo é atingir os objetivos nos pontos de bala com o mínimo nível de esforço - atingir o objetivo e não avançar mais? Caso contrário, cada um deles pode se transformar em uma toca de coelho para o desenvolvedor típico que (inclusive eu) geralmente não sabe quando deixar o suficiente em paz. :) E também que a única maneira confiável de julgar o sucesso é desenvolver e testar a API iterativamente com usuários reais ; é impossível adivinhar com precisão e leva a um cenário de excesso de engenharia.
bob
5
Eu acrescentaria que, se você realmente precisa oferecer suporte a várias bibliotecas gráficas, há quase certamente uma pronta para uso que faz tudo o que você precisa, portanto, mesmo assim, você realmente não deve criar suas próprias. (É claro que existem exceções, mas se você é inexperiente o suficiente para perguntar "quão difícil uma abstração devo fazer", provavelmente você não está trabalhando em um projeto que exige que você o faça)
Fund Monica's Lawsuit
Eu não sou um desenvolvedor gráfico, mas olhando para estruturas de compatibilidade do histórico de bancos de dados e sistemas operacionais, eu acrescentaria que quase certamente não vale a pena criar sua própria estrutura geral . A estrutura quase certamente terá que sacrificar o desempenho por compatibilidade, o que provavelmente significa que você não pode fazer muito com esses recursos especializados. É quase certo que as estruturas existentes lidam melhor com esses problemas devido ao uso mais amplo. Agora, se você tem um orçamento enorme que descreve e deseja criar uma estrutura especializada (por exemplo, para um jogo ou série), isso pode ser mais viável.
precisa saber é
6

Comece identificando o que você realmente precisa da parte "wrapper" da API. Geralmente, é muito, muito simples: você precisa dos recursos básicos (buffers, shaders, texturas, estado do pipeline) e uma maneira de usar esses recursos para construir um quadro enviando algumas chamadas de empate.

Tente manter qualquer lógica de alto nível fora da parte do invólucro da API. Se você implementar uma técnica inteligente de seleção de cenas nesta parte da API, agora você está pronto para duplicar essa lógica em todas as implementações de back-end. Isso exige muito esforço, portanto, mantenha-o simples. O gerenciamento de cenas deve fazer parte de uma parte de nível superior da API que usa o wrapper, em vez de fazer parte do próprio wrapper.

Escolha os alvos que você apoiará e entenda. É difícil escrever wrappers decentes para "tudo" e você provavelmente não precisa (provavelmente também não precisa escrever um único wrapper, como observado na resposta de Philipp ). É quase impossível escrever um invólucro decente se você ainda não conhece as APIs que irá embrulhar.

Avalie o estado da sua API regularmente. Em geral, ele deve ter uma área de superfície menor que as APIs agrupadas subjacentes; se você criar tipos de invólucros individuais para cada estrutura do D3D ou para cada chamada de função do OpenGL, provavelmente está saindo do curso.

Veja o que foi feito antes. Sokol e BGFX são APIs que fornecem níveis de agnosticismo que podem ser úteis para você e são relativamente fáceis de entender (especialmente o primeiro).

Josh
fonte
3

Outro ponto ainda não mencionado que você deve considerar é quais são seus objetivos de desempenho. Se seu objetivo é ter uma biblioteca de gráficos que produza um bom desempenho com uma plataforma de hardware barata, mas também possa ser usada em uma variedade de plataformas que são muito mais poderosas, mas usam uma API diferente, pode fazer sentido projetar sua API quaisquer abstrações usadas nativamente na plataforma em que o desempenho é um problema. Mesmo que isso cause uma degradação de velocidade de 50% nas plataformas mais poderosas, pode valer a pena se permitir uma melhoria de velocidade de 20% na plataforma onde o desempenho é mais importante.

supercat
fonte