Поделиться через


Косвенная прорисовка

Непрямое рисование позволяет перемещать некоторые сцены и отбрасывания из ЦП в GPU, что может повысить производительность. Буфер команд можно создать с помощью ЦП или GPU.

Подписи команд

Объект сигнатуры команды (ID3D12CommandSignature) позволяет приложениям указывать косвенный рисунок, в частности задать следующее:

  • Формат буфера косвенного аргумента.
  • Тип команды, который будет использоваться (из методов Id3D12GraphicsCommandList DrawInstanced, DrawIndexedInstanced или Dispatch).
  • Набор привязок ресурсов, который будет изменять вызов для каждой команды и набор, который будет унаследован.

При запуске приложение создает небольшой набор подписей команд. Во время выполнения приложение заполняет буфер командами (независимо от того, что означает, что разработчик приложения выбирает). Команды, которые при необходимости содержат состояние для задания представлений буфера вершин, представлений буфера индекса, корневых констант и корневых дескрипторов (необработанных или структурированных SRV/UAV/CBV). Эти макеты аргументов не являются аппаратными, поэтому приложения могут создавать буферы напрямую. Сигнатура команды наследует оставшееся состояние из списка команд. Затем приложение вызывает ExecuteIndirect, чтобы указать GPU интерпретировать содержимое буфера косвенного аргумента в соответствии с форматом, определенным определенной сигнатурой команды.

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

Состояние подписи команды не утечет обратно в список команд после завершения выполнения. Но после ExecuteIndirect все привязки сбрасываются на известные значения. В частности:

  • Если сигнатура команды привязывает буфер вершин к конкретному слоту, то после вызова ExecuteIndirect буфер вершин NULL привязан к данному слоту.
  • Если сигнатура команды привязывает буфер индекса, то после ExecuteIndirect буфер индекса NULL привязан.
  • Если сигнатура команды задает корневую константу, то после вызова ExecuteIndirect значение корневой константы равно 0.
  • Если сигнатура команды задает корневое представление (CBV/SRV/UAV), то после вызова ExecuteIndirect корневое представление имеет значение NULL.

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

  • Значение одной корневой константы.
  • Аргументы рисования (число вершин, число экземпляров и т. д.).

Буфер косвенного аргумента, созданный приложением, будет содержать массив записей фиксированного размера. Каждая структура соответствует одному вызову рисования. Каждая структура содержит аргументы рисования и значение корневой константы. Количество вызовов рисования указывается в отдельном буфере, видимом GPU.

Ниже приведен пример буфера команд, созданного приложением:

Формат буфера команд

Структуры буфера косвенных аргументов

Следующие структуры определяют, как конкретные аргументы отображаются в непрямом буфере аргументов. Эти структуры не отображаются в API D3D12. Приложения используют эти определения при записи в непрямой буфер аргументов (с ЦП или GPU):

Создание сигнатуры команд

Чтобы создать сигнатуру команды, используйте следующие элементы API:

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

Корневую сигнатуру необходимо указать, если и только если сигнатура команды изменяет один из корневых аргументов.

Для корневого SRV/UAV/CBV указанный размер приложения равен байтам. Слой отладки проверяет следующие ограничения адреса:

  • CBV — адрес должен иметь несколько 256 байт.
  • Необработанный SRV/UAV — адрес должен иметь несколько 4 байта.
  • Структурированный SRV/UAV — адрес должен быть нескольким из байтов структуры (объявлен в шейдере).

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

В следующих разделах показаны некоторые примеры подписей команд.

Нет изменений аргументов

В этом примере буфер косвенного аргумента, созданный приложением, содержит массив 36-байтовых структур. Каждая структура содержит только пять параметров, переданных в DrawIndexedInstanced (плюс заполнение).

Следующий код для создания описания подписи команды:

D3D12_INDIRECT_ARGUMENT_DESC Args[1];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 36;
ProgramDesc.NumArgumentDescs = 1;
ProgramDesc.pArguments = Args;

Макет одной структуры в непрямом буфере аргументов:

Байт Description
0:3 IndexCountPerInstance
4:7 Счетчикэкземпляров
8:11 StartIndexLocation
12:15 BaseVertexLocation
16:19 StartInstanceLocation
20:35 Заполнение

 

Корневые константы и буферы вершин

В этом примере каждая структура в непрямом буфере аргументов изменяет две корневые константы, изменяет одну привязку буфера вершины и выполняет одну неиндексированную операцию рисования. Между структурами нет заполнения.

Код для создания описания подписи команды:

D3D12_INDIRECT_ARGUMENT_DESC Args[4];
Args[0].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[0].Constant.RootParameterIndex = 2;
Args[0].Constant.DestOffsetIn32BitValues = 0;
Args[0].Constant.Num32BitValuesToSet = 1;

Args[1].Type = D3D12_INDIRECT_ARGUMENT_TYPE_CONSTANT;
Args[1].Constant.RootParameterIndex = 6;
Args[1].Constant.DestOffsetIn32BitValues = 0;
Args[1].Constant.Num32BitValuesToSet = 1;

Args[2].Type = D3D12_INDIRECT_ARGUMENT_TYPE_VERTEX_BUFFER_VIEW;
Args[2].VertexBuffer.Slot = 3;

Args[3].Type = D3D12_INDIRECT_ARGUMENT_TYPE_DRAW;

D3D12_COMMAND_SIGNATURE_DESC ProgramDesc;
ProgramDesc.ByteStride = 40;
ProgramDesc.NumArgumentDescs = 4;
ProgramDesc.pArguments = Args;

Макет одной структуры в непрямом буфере аргументов имеет следующий вид:

Байт Description
0:3 Данные для корневого индекса параметров 2
4:7 Данные для корневого индекса параметров 6
08:15 Виртуальный адрес VB в слоте 3 (64-разрядная версия)
16:19 Размер VB
20:23 Шаг VB
24:27 VertexCountPerInstance
28:31 Счетчикэкземпляров
32:35 StartVertexLocation
36:39 StartInstanceLocation

 

Учебники по расширенному обучению DirectX. Выполнение непрямого и асинхронного вычисления GPU

Непрямое рисование и очистка GPU: пошаговое руководство по коду

Отрисовка