Подтвердить что ты не робот

Программно создавая текстуры Directx 11, плюсы и минусы трех разных методов

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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