2013-06-18 4 views
1

Я пытался реализовать систему частиц на основе Compute Shader.Показатели счетчика БПЛА, используемые в нескольких шейдерах?

У меня есть вычислительный шейдер, который строит структурированный буфер частиц, используя БПЛА с флагом D3D11_BUFFER_UAV_FLAG_COUNTER.

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

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

Однако во втором вычислительном шейдере я бы оценил, что около 5% индексов ошибочны - они принадлежат другим частицам, которые не поддерживают обнаружение столкновений.

Вот вычислитель код шейдера, который perfroms в здании списка:

// append to destination buffer 
uint dstIndex = g_dstParticles.IncrementCounter(); 
g_dstParticles[ dstIndex ] = particle; 

// add to behaviour lists 
if (params.flags & EMITTER_FLAG_COLLISION) 
{ 
    uint behaviourIndex = g_behaviourCollisionIndices.IncrementCounter(); 
    g_behaviourCollisionIndices[ behaviourIndex ] = dstIndex; 
} 

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

Я подозреваю, что IncrementCounter на самом деле не гарантированно возвращает уникальный индекс в БПЛА и что происходит некоторая умная оптимизация, что означает, что индекс действителен только в вычислительном шейдере, в котором он используется. И, таким образом, моя попытка передать его во второй вычислительный шейдер недействителен.

Может ли кто-нибудь дать конкретные ответы на то, что здесь происходит? И если у меня есть способ сохранить фильтрацию внутри одного и того же вычислительного шейдера в качестве основного обновления?

Спасибо!

ответ

1

IncrementCounter - это атомарная операция, и, таким образом, (несмотря на ошибки, связанные с драйверами и аппаратными средствами), возвращать уникальное значение каждому потоку, который его вызывает.

Задумывались ли вы об использовании буферов Append/Consume для этого, так как они предназначены для них? Первый проход просто присоединяет сложные частицы столкновения к AppendStructuredBuffer, а второй - из одного и того же буфера, но вместо этого использует представление ConsumeStructuredBuffer. Второй запуск вычислений должен будет использовать DispatchIndirect, поэтому вы будете запускать столько групп потоков, сколько необходимо для числа в списке (то, что CPU не знает).

Обычные рекомендации применяются, хотя вы пробовали слой Debug D3D11 и запускали его на эталонном устройстве, чтобы убедиться, что это не проблема с драйвером?

+0

Спасибо за информацию - это в значительной степени то, что я думал. Я тестировал код на другом оборудовании 2-х графических вендоров и нашел, что он отлично работает на них, поэтому это должно быть проблемой с аппаратным/драйвером, на котором я тестировал. Я отправил отчет об ошибках и воспроизвел их. – Hybrid

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