Как использовать UpdateSubresource и Map / Unmap?

8

Из того, что я понял (из чтения различных страниц), есть 2 способа обновления буфера:

  1. UpdateSubresource()(когда буфер создается с DEFAULTиспользованием)
  2. Map(), скопируйте новые данные, Unmap()(когда буфер создан с DYNAMICиспользованием)

В первом случае я вызываю только эту функцию (больше ничего)? Потому что я видел, как люди говорят, что они отображают буфер, а затем обновляют подресурс, или, может быть, я их неправильно понял.

И есть ли другой способ (сомневаюсь: P)? Я правильно понимаю вещи?

NPS
источник

Ответы:

11

Об этом есть хорошая презентация: « Не выбрасывайте все это: эффективное управление буфером » Джона Макдональда из NVIDIA. Она охватывает различные темы, но по теме вашего вопроса, то общий совет для создания буферов с динамическим использованием и использованием Map()с D3D11_MAP_WRITE_DISCARD, когда необходимо часто обновлять (например , каждый кадр, или несколько раз за кадр) данных. Это будет использоваться для постоянных буферов, буферов вершин для систем частиц и тому подобного.

Согласно презентации, использование по умолчанию / UpdateSubresource()требует больше ресурсов процессора, чем динамическое использование / Map(). Однако он рекомендует использовать по умолчанию / UpdateSubresource()для данных, которые необходимо обновлять только один раз в течение некоторого времени, таких как данные, передаваемые с диска в игре с открытым миром.

И да, в случае, когда вы используете UpdateSubresource(), вы бы использовали его отдельно, а не в сочетании с Map().

Натан Рид
источник
2
Странно, вы оба ответили в одну минуту и ​​опубликовали одну и ту же ссылку.
NPS
В другой ветке вы писали: «Вам не нужно связывать буфер, чтобы обновить его с помощью UpdateSubresource. Фактически, его не следует связывать при обновлении». Означает ли это, что я всегда должен отсоединять все буферы перед их обновлением? Если это так, как я могу отменить привязку буфера?
NPS
1
@NPS Прежде всего, это будет неявно не связано, если вы уже связали что-то другое на его месте. В противном случае вы можете явно связать NULL, чтобы отменить привязку буфера. Например, вы можете ID3D11ShaderResourceView * nullsrv = NULL; pCtx->PSSetShaderResources(0, 1, &nullsrv);отменить привязку текстуры из слота 0.
Натан Рид,
Я знал о неявном, но нуждался в явном, спасибо. Но вы не ответили на мой первый вопрос - нужно ли делать это всегда для всех буферов, которые я собирался обновить?
NPS
1
@NPS В идеале буфер не должен использоваться графическим процессором во время его обновления на процессоре. Но графический процессор и процессор работают асинхронно, поэтому это непросто обеспечить. Я бы сказал, не беспокойтесь об этом, если вы не обнаружите, что это реальная проблема производительности.
Натан Рид
2

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

Map / Unmap следует использовать, когда ресурс будет обновляться очень часто (т. Е. Каждый кадр), например, некоторые постоянные буферы. Наиболее распространенным случаем является перезапись всего буфера с помощью WriteDiscard. Есть презентация nVidia, где они рекомендуют эту практику.

Странник
источник