Al hacer un renderizador que admita múltiples API de gráficos, normalmente querrá abstraer su código en algún tipo de biblioteca de bajo nivel que esté vinculada con algunas API de gráficos como OpenGL, Vulkan, D3D11, etc.
Funcionan de manera muy diferente entre sí, por lo que es esencial hacer una buena API genérica; He leído que normalmente querría usar un "back-end" que implementa la funcionalidad básica para cada API que desea admitir, y un "front-end" que es lo que utiliza el programador para dibujar cosas en el pantalla.
¿Cómo sé si estoy haciendo demasiada abstracción?
graphics-programming
Gabriele Vierti
fuente
fuente
Respuestas:
En primer lugar, considere si realmente vale la pena admitir más de una API de gráficos. El simple uso de OpenGL cubrirá la mayoría de las plataformas y será "lo suficientemente bueno" para todos, excepto para los proyectos gráficamente más ambiciosos. A menos que trabaje para un estudio de juegos muy grande que pueda permitirse dedicar varios miles de horas-persona a implementar y probar múltiples backends de renderizado y, a menos que haya algunas características específicas de DirectX o Vulcan que realmente quiera mostrar, generalmente no vale la pena la molestia . Especialmente teniendo en cuenta que puede ahorrar mucho trabajo utilizando una capa de abstracción que otra persona creó (una biblioteca de terceros o un motor de juego).
Pero supongamos que ya evaluó sus opciones y llegó a la conclusión de que es viable y que vale la pena dedicar las suyas.
Entonces, el juez principal de la arquitectura de software de su capa de abstracción son sus programadores front-end.
Si es así, lo lograste.
fuente
Comience por identificar lo que realmente necesita de la parte de "envoltura" de la API. En general, es muy, muy simple: necesita los recursos básicos (buffers, sombreadores, texturas, estado de canalización) y una forma de usar esos recursos para construir un marco enviando algunas llamadas de sorteo.
Intente mantener cualquier lógica de alto nivel fuera de la parte del contenedor de la API. Si implementa una técnica inteligente de eliminación de escenas en esta parte de la API, ahora está en el gancho para duplicar esa lógica en todas las implementaciones de back-end. Eso es mucho esfuerzo adicional, así que manténgalo simple. La gestión de escenas debe ser parte de una porción de nivel superior de la API que usa el contenedor en lugar de ser parte del contenedor.
Elige los objetivos que apoyarás y entiéndelos. Es difícil escribir envoltorios decentes para "todo", y probablemente no sea necesario (posiblemente tampoco es necesario escribir un envoltorio único, como se señala en la respuesta de Philipp ). Es casi imposible escribir un contenedor decente si no conoce las API que ya va a ajustar.
Evaluar el estado de su API regularmente. En general, debe tener un área de superficie más pequeña que las API envueltas subyacentes; si se encuentra creando tipos de envoltura uno a uno para cada estructura D3D o cada llamada a la función OpenGL, probablemente se está desviando del rumbo.
Mira qué trabajo ha ido antes. Sokol y BGFX son API que proporcionan niveles de agnosticismo que pueden ser útiles para usted y que son relativamente fáciles de entender (especialmente el primero).
fuente
Otro punto aún no mencionado que debe considerar es cuáles son sus objetivos de rendimiento. Si su objetivo es tener una biblioteca de gráficos que produzca un buen rendimiento de una plataforma de hardware barata, pero que también se pueda usar en una variedad de plataformas que son mucho más potentes pero que usan una API diferente, puede tener sentido diseñar su API en torno a cualesquiera que sean las abstracciones que se usen de forma nativa en la plataforma donde el rendimiento es un problema. Incluso si esto causa una degradación de la velocidad del 50% en las plataformas más potentes, puede valer la pena si permite una mejora de la velocidad del 20% en la plataforma donde el rendimiento es más importante.
fuente