2013-09-23 4 views
0

Я пытаюсь реализовать один комплексный алгоритм с использованием графического процессора. Единственная проблема - ограничения HW, а максимальный доступный уровень функции - 9_3.DirectX 11, Объединение пиксельных шейдеров для предотвращения узких мест

Алгоритм - это, в основном, алгоритм «сопоставления стерео» для двух изображений. Из-за упомянутых ограничений все вычисления должны выполняться только в вершинных/пиксельных шейдерах (нет доступных API вычислений). Вершинные шейдеры здесь бесполезны, поэтому я рассматривал их как сквозные шейдеры вершин.

Позвольте мне коротко описать алгоритм:

  1. Возьмите два изображения и вычисления карты объема затрат (в основном conterting RGB в оттенки серого -> перевести правильное изображение на D и вычесть его из левого изображения). Этот шаг повторяется примерно 20 раз для разных D, который генерирует Texture3D.

    Проблема здесь: Я не могу просто создать один Pixel Shader, который вычисляет эти 20 повторений в один раз из-за размером ограничения Pixel Shader, поэтому я вынужден позвонить Draw (макс 512 арифметики.)() в цикле на C++, который ненужно связан с CPU, когда все операции выполняются на с теми же двумя изображениями - мне кажется, что у меня есть одно узкое место здесь. Я знаю, что есть несколько целей рендеринга, но: есть макс. 8 (мне нужно 20+), если я хочу сгенерировать 8 результатов в одном пиксельном шейдере, я превышу его ограничение по размеру (512 арифметических для моего HW).

  2. Тогда мне нужно вычислить для каждого из вычисленной текстуры коробки фильтра с окнами, где г> 9.

    Еще одна проблема: Поскольку окно является настолько большим, мне нужно разделить окно фильтрации в два пиксельных шейдера (вертикальное и горизонтальное направление отдельно), потому что петли разворачивают результаты сцены с очень длинным кодом. Ручная реализация этих циклов не поможет, потому что он будет создан для большого пиксельного шейдера. Так вот еще узкое место здесь - CPU должен быть задействован для передачи результатов от текстуры temp (результат V-прохода) до второго прохода (H pass).

  3. Затем на следующем этапе для каждой пары результатов с 1-го шага и 2-го шага применяются некоторые арифметические операции.

    Я еще не пришел сюда с моим развитием, поэтому не знаю, какие узкие места ждут меня здесь.

  4. Тогда минимальное D (значение параметра из 1-го шага) берется для каждого пиксела на основе значения пикселя с шага 3.

    ... такой же, как на шаге 3.

Здесь в основном ОЧЕНЬ простой график, показывающий мою текущую реализацию (исключая шаги 3 и 4).

Problem diagram

красные точки/кружки/независимо представляют собой временные буферы (текстуры), где частичные результаты сохраняются и при каждом красной точкой CPU становится участие.

Вопрос 1: Невозможно ли каким-либо образом позволить GPU знать, как выполнять каждую форму ветви до дна, не вовлекая процессор и приводя к узкому месту? То есть программировать последовательность графических конвейеров за один раз, а затем позволить графическому процессору выполнять свою работу.

Еще один вопрос о визуализации для текстуры: все ли текстуры постоянно хранятся в памяти графического процессора даже между вызовами метода Draw() и переключением пиксельных/вершинных шейдеров? Или есть передача с GPU на CPU, происходящее ... Потому что это может быть еще одна проблема, которая приводит к узкому месту.

Любая помощь будет оценена!

Заранее спасибо.

С наилучшими пожеланиями, Лукаш

ответ

1

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

1. Shader повторение

Прежде всего, непонятно, что вы называете "узким местом" здесь. Да, теоретически, draw calls in for loop - потеря производительности. Но это узкое место? Ваше приложение действительно теряет производительность здесь? Сколько? На это могут ответить только профилировщики (CPU и GPU). Но чтобы запустить его, вы должны сначала завершить свой алгоритм (этапы 3 и 4). Итак, я бы лучше придерживался текущего решения и начал реализовывать весь алгоритм, затем профиль и проблемы с производительностью.

Но, если вы чувствуете себя готовым к настройкам ... Обычная технология повторения. Вы можете создать еще один буфер вершин (буфер буфера), который будет содержать параметры не для каждой вершины, а для одного экземпляра draw. Затем вы делаете все с одним звонком DrawInstanced().

Для первого этапа буфер экземпляра может содержать значение D и индекс цели Texture3D слой. Вы можете передать их из вершинного шейдера.

Как всегда, у вас есть торговля здесь: простота использования кода (возможно).

2.Мульти-проход рендеринга

процессор должен быть вовлечен, чтобы передать результаты от темп текстуры (результат V прохода) для второго прохода (Н проход)

Как правило, вы цепочки, как это , поэтому нет CPU не участвует:

// Pass 1: from pTexture0 to pTexture1 
// ...set up pipeline state for Pass1 here... 
pContext->PSSetShaderResources(slot, 1, pTexture0); // source 
pContext->OMSetRenderTargets(1, pTexture1, 0);  // target 
pContext->Draw(...); 

// Pass 2: from pTexture1 to pTexture2 
// ...set up pipeline state for Pass1 here... 
pContext->PSSetShaderResources(slot, 1, pTexture1); // previous target is now source 
pContext->OMSetRenderTargets(1, pTexture2, 0); 
pContext->Draw(...); 
// Pass 3: ... 

Обратите внимание, что pTexture1 должны иметь как D3D11_BIND_SHADER_RESOURCE и D3D11_BIND_RENDER_TARGET флаги. Вы можете иметь несколько текстур ввода и несколько целей рендеринга. Просто убедитесь, что каждый следующий проход знает, какие выходы предыдущего прохода. И если предыдущий проход использует больше ресурсов, чем нынешние, не забудьте отвязать ненужный, чтобы предотвратить труднодоступные найти ошибки: расположение данных

pContext->PSSetShaderResources(2, 1, 0); 
pContext->PSSetShaderResources(3, 1, 0); 
pContext->PSSetShaderResources(4, 1, 0); 
// Only 0 and 1 texture slots will be used 

3. Ресурсный

ли все текстуры постоянно сохраняются в памяти GPU даже между вызовами метода Draw() и переключением шейдеров Pixel/Vertex?

Мы никогда не узнаем об этом. Драйвер выбирает подходящее место для ресурсов. Но если у вас есть ресурсы, созданные с использованием DEFAULT и 0 Плюс доступа к ЦП, вы можете быть почти уверены, что он всегда будет в видеопамяти.

Надеюсь, это поможет. Счастливое кодирование!

+0

Спасибо за ваш ответ! –

+0

Вы развеяли мои сомнения. Проблема с моей разработкой заключается в том, что я разрабатываю для мобильного устройства, и я не могу найти подходящий профилировщик GPU для этого. Возможно, я попытаюсь запустить свой код на каком-то старом ПК со «сравнимой» производительностью, чтобы увидеть, как он себя ведет. Еще раз спасибо! –

Смежные вопросы