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?
graphics-programming
Gabriele Vierti
fonte
fonte
Respostas:
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.
Se sim, você conseguiu.
fonte
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).
fonte
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.
fonte