Самый низкий уровень, который имеет смысл с моей точки зрения, это то, что говорит о ресурсах, задействованных в рендеринге - vb / ib, рендеринг поверхностей, текстур, шейдеров, блоков состояния и т. Д.
Проблема здесь в том, что некоторые из них должны быть в разных форматах, в зависимости от API - вот где это становится немного сложнее. Самый простой способ обойти это - предварительно обработать статические ресурсы для соответствующего API. Для динамических, используйте только шейдеры, чтобы генерировать их - это позволяет довольно просто оставаться в нативных форматах.
Все, что вы затем делаете на более высоком уровне, это настраивает конвейеры с подключенными ресурсами и передает их в графический процессор. Вы обнаружите, что таким образом не все может быть абстрагировано, особенно, если вы используете аппаратные приемы. Но это хорошее начало.
(Замечание: если вы рассматриваете трюки, специфичные для платформы, как особый вид ресурса, вы можете далеко продвинуть эту концепцию.)
Таким образом, в некотором роде вы создадите две вещи: менеджер аппаратных ресурсов и набор инструментов для настройки DAG из этих ресурсов.