Программное создание текстур DirectX 11, плюсы и минусы трех разных методов - PullRequest
13 голосов
/ 14 июня 2011

Документация msdn объясняет, что в DirectX 11 существует несколько способов программного заполнения текстуры DirectX 11:

(1) Создайте текстуру с текстурой использования по умолчанию и инициализируйте ее данными из памяти

(2) Создайте текстуру с динамическим использованием, используйте DeviceContext Map, чтобы получить указатель на память текстур, запишите в нее, затем используйте Unmap, чтобы указать, что вы сделали (в этот момент я думаю, что это скопировано в GPU)

(3) Создайте текстуру с использованием промежуточной обработки и выполните те же шаги, что и для динамической текстуры, но выполните это с вызовом ID3D11DeviceContext.CopyResource, чтобы использовать эту промежуточную текстуру, чтобы в свою очередь заполнить (неизменную) стандартную или динамическую текстуру.

Однако в документации вообще не объясняются плюсы и минусы каждого метода, и я все еще новичок в directx, поэтому мне это не совсем понятно.

Каковы плюсы и минусы каждого из этих способов программного создания текстуры в DirectX 11?

Примечание: Я читал, что в контексте размещения текстур чтение обратно из gpu не буферизуется, поэтому вы должны выполнить свою собственную двойную буферизацию. Но я не знаю, было ли это точно и относится ли это к написанию с использованием промежуточных текстур (или даже к тому, что оно означает)

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

1 Ответ

22 голосов
/ 30 июня 2011

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

При условии, что в памяти приложения есть данные, которые вы хотите поместить в текстуру:

Если это просто статическая текстура (я имею в виду, что текстура читается из гораздо большего, чем записывается)в), тогда вам нужна текстура USAGE_DEFAULT или USAGE_IMMUTABLE.Как правило, они оптимизированы для производительности чтения GPU по сравнению с USAGE_DYNAMIC.Если у вас есть данные, удобные при создании текстуры, тогда опция (1) является самой простой, использует наименьшую промежуточную память, а в DX11 передача данных в графический процессор может выполняться в отдельном потоке от вашего потока рендеринга.Если у вас нет данных во время создания текстуры, используйте UpdateSubresource () или option (3), чтобы предоставить данные, когда они у вас есть.

Если это динамическая текстура, то есть вы предоставляете данныеновое содержимое из ЦП часто (воспроизведение видео на основе ЦП является каноническим случаем: данные предоставляются ЦП один раз за кадр, а затем считываются ГП один раз за кадр), тогда вы, вероятно, захотите использовать USAGE_DYNAMIC и параметр (2).Текстуры USAGE_DYNAMIC оптимизированы для потоковой передачи данных из ЦП в ГП, а не просто для чтения ГП.Детали (и последствия для производительности) различаются у разных поставщиков оборудования, но обычно вы хотите использовать USAGE_DYNAMIC, только если вы действительно передаете данные с CPU на GPU, а не просто потому, что это удобный способ загрузки статических данных заранее.

Опция (3) является более специализированной и может использоваться для начальной загрузки данных в статическую текстуру (повторное использование промежуточных поверхностей для загрузки данных для многих текстур) или для потоковой передачи данных для относительно динамического использования.Это дает вам точный контроль над синхронизацией GPU / CPU и промежуточной памяти, используемой для передачи.Обычно вы используете кольцо промежуточных буферов и D3D11_MAP_FLAG_DO_NOT_WAIT, чтобы проверить, используется ли каждый буфер предыдущим CopyResource.Я считаю, что это вариант эксперта - если вы не будете осторожны, вы можете сильно повредить производительности, не допуская асинхронной работы процессора и графического процессора.

Полное раскрытие: я работаю над драйвером D3D в Nvidia, но этомои личные мнения.

...