Единственный общий ответ, который я могу дать на ваш первый вопрос: «Это зависит». Насколько мне известно, Direct3D11 не отслеживает состояние своего конвейера, чтобы избежать избыточных изменений состояния.
Некоторые поставщики могут решить реализовать такую функцию в своих драйверах, но я бы не стал рассчитывать наэто. Лучше предположить, что трижды вызов одного и того же метода будет стоить в три раза дороже, чем вызов его один раз.
Относительно вашего второго вопроса: Да, есть издержки *. Всякий раз, когда вы вызываете метод DirectX, при условии, что происходит переключение контекста (переключение с контекста приложений на контекст драйверов), что требует времени.
Большинство механизмов рендеринга, которые я видел, запоминают текущее состояние контекста, чтов сочетании с сортировкой вызовов рендеринга, доказательства того, что они достаточно эффективны.
(*) Это основано на моих знаниях из лекций об операционных системах и компьютерной графике. Возможно, он не применим к Direct3D11 и / или устарел.
РЕДАКТИРОВАТЬ: решение вопроса в комментарии, поскольку оно не вписывается в комментарий.
Q: Можете ли вы подробнее рассказать о "сортировке вызовов рендеринга"?
Изменение состояния часто приводит к его штрафу. Поэтому мы хотим уменьшить количество необходимых изменений состояния.
Давайте немного подумаем о более широкой картине. Перед выполнением любого вызова отрисовки вы обычно связываете свои буферы, шейдеры и так далее. Таким образом, для каждого вызова отрисовки у нас есть назначенное ему состояние (или конфигурация). Мы можем представить это состояние с помощью кортежа объектов состояния, например:
vertex_buffer a;
index_buffer b;
shader c;
shader d;
render_target e;
pipeline_state state{a, b, c, d, e};
// Then later use...
set_pipeline_state(state);
render_amazing_stuff();
Теперь давайте предположим, что мы хотим нарисовать 3 объекта с немного другой конфигурацией.
vertex_buffer a, b, c; // a stores the first model, b the second, ...
index_buffer f, g;
shader c;
shader d;
render_target e;
pipeline_state state1{a, f, c, d, e};
pipeline_state state2{b, f, c, d, e};
pipeline_state state3{b, g, c, d, e};
У нас есть 3 состояния конвейера, которые отличаются незначительно. Мы можем либо повысить нашу производительность, переупорядочив вызовы отрисовки по их состоянию конвейера, чтобы уменьшить разницу между ними.
set_pipeline_state(state1); // Set initial state, with all buffers..
render();
set_pipeline_state(state2); // Binds only the new vertex buffer; since it's the only difference.
render();
set_pipeline_state(state3); // Binds only the new index buffer; since it's the only difference.
render();
Разница между всеми состояниями минимальна, сокращая количество изменений состояния, эффективно даваяувеличение кадров в секунду.