¿Cómo sé si estoy abstrayendo demasiado las API de gráficos?

23

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?

Gabriele Vierti
fuente
55
¿Está 100% seguro de que su envoltorio + Vulkan o D3D11 es más rápido que simplemente usar OpenGL?
Mooing Duck
@ Moooing Duck si se usa correctamente, sí.
Gabriele Vierti
44
Lo dudaría seriamente. La mayoría de las ganancias en Vulkan provienen de ser de muy bajo nivel y de hacer las cosas de una manera muy peculiar y específica. Algo que es lo suficientemente genérico como para hacer lo mismo sin problemas en OpenGL o D3D, casi con seguridad no puede hacer eso. Reimplementar las mismas cosas que OpenGL (como hacen muchos tutoriales de Vulkan, irónicamente) resulta en un 99.99% del mismo rendimiento, con 20 veces el trabajo.
Damon
@Damon es cierto, pero las API más nuevas están específicamente diseñadas (y no adaptadas como OpenGL) para funcionar en gpus modernos; En términos de Vulkan, puede más o menos usar la misma API en cada plataforma soportada, al contrario de OpenGL, donde tiene que utilizar el "Embedded Systems" versión. Aparte de menos gastos generales de CPU y características sofisticadas, no tenemos mucho, pero en el futuro podríamos tener algunas técnicas bastante sorprendentes que pueden ejecutarse más rápido usando Vk o D3D12 en lugar de OGL o D3D11
Gabriele Vierti

Respuestas:

44

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.

  • ¿Son capaces de implementar los sistemas de juego que desean implementar sin tener que preguntarse acerca de los detalles de bajo nivel?
  • ¿Pueden ignorar por completo que hay más de una API de gráficos?
  • ¿Teóricamente sería posible agregar otro backend de representación sin cambiar ninguno de los códigos front-end?

Si es así, lo lograste.

Philipp
fuente
2
Una sugerencia adicional: ¿vale la pena enfatizar que el objetivo es lograr los objetivos en las viñetas con el mínimo nivel de esfuerzo, simplemente alcanzar el objetivo y no avanzar más? De lo contrario, cada uno de estos puede convertirse en un agujero de conejo para el desarrollador típico que (incluido yo mismo) a menudo no sabe cuándo dejar lo suficientemente bueno. :) Y también que la única forma confiable de juzgar el éxito es desarrollar y probar la API de forma iterativa con usuarios reales ; Es imposible adivinar con precisión, y conduce a un escenario de madriguera de conejo.
bob
55
Yo añadiría que, si realmente no tiene que soportar múltiples bibliotecas de gráficos, no hay casi ciertamente un off-the-shelf uno que hace todo lo que necesita, por lo que incluso entonces usted realmente no debe rodar su propia. (Por supuesto, hay excepciones, pero si eres lo suficientemente inexperto como para preguntar "qué tan estricta debería ser una abstracción", probablemente no estés trabajando en un proyecto que requiera que lo hagas)
Financia la demanda de Mónica el
No soy un desarrollador de gráficos, pero mirando los marcos de compatibilidad del historial de bases de datos y sistemas operativos, agregaría que casi seguro que no vale la pena crear su propio marco general . El marco casi seguro tendrá que sacrificar el rendimiento por compatibilidad, lo que probablemente significa que no puede hacer mucho con esas características especializadas de todos modos. Es casi seguro que los marcos existentes manejarán mejor esos problemas debido al uso más amplio. Ahora, si tiene el presupuesto masivo que describe y desea construir un marco especializado (digamos para un juego o serie), eso podría ser más factible.
jpmc26
6

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).

Josh
fuente
3

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.

Super gato
fuente