Управление графическим состоянием и компонентами?

11

Я часто склонен делать преждевременную оптимизацию при работе с графикой. Есть несколько принципов, которым я всегда стараюсь следовать:

  • Сократите количество компонентов D3D до минимума. (Рендеринг состояний, буферов, шейдеров и т. Д.)
  • Связывайте компоненты только в случае крайней необходимости. (Уже не связаны и т. Д.)
  • Специализируйте компоненты как можно больше. (Только установите необходимые BindFlags и т. Д.)

Это привело меня к созданию очень сложных оболочек для управления созданными компонентами и текущим состоянием конвейера. Это не только отнимает у меня много драгоценного времени на разработку, но также добавляет еще один большой уровень сложности.

И что хуже всего: я даже не знаю, стоит ли это того.

Некоторые из моих соображений по оптимизации уже могут быть реализованы на более низком уровне, и я просто копирую их, дополнительно тратя время на процессор. Другие соображения могут быть совершенно ненужными, так как влияние на производительность незначительно.

Итак, мои вопросы:

  1. Какие из вышеперечисленных правил действительны и в какой степени я должен им следовать?
  2. Как GPU обрабатывает изменения состояния?
  3. Что произойдет, если я изменю состояние, которое никогда не используется? (Не активен вызов при отрисовке, пока он активен.)
  4. Каковы фактические потери производительности для связывания различных компонентов?
  5. Какие еще соображения производительности следует учитывать?

Пожалуйста, не говорите мне, что я не должен заботиться о производительности, пока не достигну реальных пределов. Хотя это очевидно с практической точки зрения, я в основном интересуюсь теорией. Мне как-то нужно бороться с желанием создать оптимальную графическую среду, и я не думаю, что смогу сделать это с помощью обычной «лекции по преждевременной оптимизации».

Управление компонентами

В настоящее время я пишу приложения DirectX 11 на C #, используя SlimDX в качестве управляемой оболочки. Это очень низкоуровневая оболочка, и моя текущая абстракция построена на ней.

Есть некоторые очевидные преимущества при использовании абстракции Direct3D. Настройка среды, загрузка шейдеров, установка констант и отрисовка сетки намного проще и использует намного меньше кода. Кроме того, поскольку он управляет созданием и удалением большинства компонентов, их можно автоматически повторно использовать везде, и я почти полностью избегаю утечек памяти.

  1. Как вы обычно управляете всеми графическими компонентами и ресурсами?
  2. Можете ли вы порекомендовать какие-либо управляемые оболочки, делающие что-то похожее на мой пример ниже?

Вот пример моей текущей реализации. Я вполне доволен интерфейсом. Он обладает достаточной гибкостью для моих нужд и очень прост в использовании и понимании:

// Init D3D environment
var window = new RenderForm();
var d3d = new Direct3D(window, GraphicsSettings.Default);
var graphics = new GraphicsManager(d3d.Device);

// Load assets
var mesh = GeometryPackage.FromFile(d3d, "teapot.gp");
var texture = Texture.FromFile(d3d, "bricks.dds");

// Render states
graphics.SetViewports(new Viewport(0, 0, 800, 600);
graphics.SetRasterizer(wireFrame: false, culling: CullMode.Back);
graphics.SetDepthState(depthEnabled: true, depthWriteEnabled: true);
graphics.SetBlendState(BlendMethod.Transparency);

// Input layout
graphics.SetLayout("effect.fx", "VS", "vs_4_0",
    new InputElement("POSITION", 0, Format.R32G32B32_Float, 0),
    new InputElement("TEXCOORD", 0, Format.R32G32_Float, 0)
);

// Vertex shader
graphics.SetShader(Shader.Vertex, "effect.fx", "VS", "vs_4_0");
graphics.SetConstants(Shader.Vertex, 0, 4, stream => stream.Write(wvpMatrix));

// Pixel shader
graphics.SetShader(Shader.Pixel, "effect.fx", "PS", "ps_4_0");
graphics.SetTexture(Shader.Pixel, 0, texture);
graphics.SetSampler(Shader.Pixel, 0, Sampler.AnisotropicWrap);
graphics.SetConstants(Shader.Pixel, 0, 1, stream => stream.Write(new Color4(1, 0, 1, 0);

d3d.Run(() =>
{
    // Draw and present
    d3d.BackBuffer.Clear(new Color4(1, 0, 0.5f, 1));
    graphics.SetOutput(d3d.BackBuffer);
    graphics.Draw(mesh);
    d3d.Present();
}
Луций
источник
8
Для такого рода вопросов я бы не стал читать лекцию «преждевременная оптимизация», я бы дал вам лекцию «изменения профиля, чтобы вы могли убедиться сами».
Тетрад
@Tetrad Мне почти стыдно признаться, что это довольно приличный совет. Я определенно должен сделать больше профилирования.
Люциус
1
Профилирующие числа - это версия игры «фото или этого не произошло» от gamedev точно =)
Патрик Хьюз

Ответы:

3

Мне нравится подход абстракции, изложенный Ходжманом в следующих темах на gamedev.net:

Он описывает трехуровневую систему рендеринга:

  1. Низкоуровневый API рендеринга, который принимает «команды», абстрагируя не более чем различия между различными графическими API, такими как Direct3D 9, Direct3D 11 и OpenGL. Каждая «команда» сопоставляется с различным состоянием или вызовом отрисовки, таким как связывание потока вершин или текстуры или рисование примитивов.
  2. API, который принимает «элементы рендеринга», которые группируют все состояния и один вызов отрисовки, необходимый для рендеринга определенного объекта, и сортирует и переводит их в команды, отправляемые на первый уровень. Состояние рендеринга содержит вызов отрисовки и стек «групп состояний», которые логически группируют изменения состояния. Например, у вас будет группа состояний для прохода рендеринга, группа состояний для материала, группа состояний для геометрии, группа состояний для экземпляра и так далее. Этот уровень отвечает за сортировку этих элементов рендеринга для уменьшения избыточных изменений состояния и отбраковки любых изменений состояния, которые на самом деле являются избыточными.
  3. Системы высокого уровня, такие как граф сцены или визуализация с графическим интерфейсом, которые отправляют элементы рендеринга на второй уровень. Важно отметить, что эти системы не знают ни об алгоритмах сортировки состояний, ни о конкретном API рендеринга, что делает их полностью независимыми от платформы. Они также просты в использовании после внедрения API нижнего уровня.

В заключение, эта модель решает обе ваши проблемы одновременно.

jmegaffin
источник