Как следует использовать SetDescriptorHeaps? - PullRequest
0 голосов
/ 31 марта 2019

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

Давайте начнем с краткого фона, чтобы вы лучше поняли, о чем я прошу.

ВDirectX11, мы создали объекты разных шейдеров, а затем нам пришлось связывать каждый из них отдельно во время реального времени выполнения при настройке нашего вызова отрисовки.Вот псевдо-пример:

deviceContext->VSSetShader(...);
deviceContext->HSSetShader(...);
deviceContext->DSSetShader(...);
deviceContext->PSSetShader(...);

В DirectX12 они реализовали это намного умнее, потому что теперь мы можем вместо этого настроить состояние конвейера во время инициализации, а затем установить все вышеперечисленное с помощью одного APIЗвоните:

commandList->SetPipelineState(...);

Очень просто, элегантно и быстрее.И вдобавок ко всему, очень логично.Теперь давайте взглянем на кучи дескрипторов.Я как бы ожидал, что это будет следовать той же элегантной схеме, и это в основном то, о чем мой вопрос.

В DirectX11 мы создали объекты разных дескрипторов (представлений), а затем нам пришлось связывать каждый из них по отдельности.для каждого шейдера во время реального времени выполнения при настройке нашего вызова отрисовки.Еще раз псевдо-пример:

deviceContext->PSSetConstantBuffers(0, n, ...);
deviceContext->PSSetShaderResources(0, n, ...);
deviceContext->PSSetSamplers(0, n, ...);

В DirectX12 они реализовали нечто, называемое кучами дескрипторов.По сути, это куски памяти, которые содержат все дескрипторы, которые мы хотим связать, и мы также можем настроить их во время инициализации.Пока это выглядит так же элегантно, как состояние конвейера, поскольку мы можем установить все с помощью одного вызова API:

commandList->SetDescriptorHeaps(n, ...);

Или мы можем?Вот здесь и возникает путаница, потому что после поиска я обнаружил этот вопрос , в котором говорится:

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

Между тем в документации MSDN для SetDesciptorHeaps ничего не говорится об этом методе, который стоит особенно дорого.

Учитывая, как элегантно они спроектировали состояние конвейераЯ ожидал, что смогу сделать это:

commandList->SetPipelineState(...);
commandList->SetDescriptorHeaps(n, ...);
commandList->DrawInstanced(...);

commandList->SetPipelineState(...);
commandList->SetDescriptorHeaps(n, ...);
commandList->DrawInstanced(...);

commandList->SetPipelineState(...);
commandList->SetDescriptorHeaps(n, ...);
commandList->DrawInstanced(...);

Но если SetDescriptorHeaps действительно так дорого, это, вероятно, обеспечит очень плохую производительность.Или это будет?Как я уже сказал, я не могу найти никаких утверждений о том, что это действительно плохая идея в MSDN.

Поэтому мои вопросы:

  • Если вышеупомянутое считается плохой практикой, как следуетSetDescriptorHeaps использоваться?
  • Если это проблема с производительностью только для Nvidia, почему они не исправляют свои драйверы?

По сути, я хочу сделать следующее:иметь две кучи дескриптора (CBV / SRV / UAV + сэмплер) для каждого состояния конвейера.И, судя по тому, насколько дешево изменить состояние конвейера, было бы логично, чтобы изменение кучи дескриптора было бы столь же дешевым.Состояние конвейера и куча дескрипторов довольно тесно связаны, то есть изменение состояния конвейера, скорее всего, потребует другого набора дескрипторов.

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

...