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


Вспомогательные списки команд

Этот раздел относится только к Windows 7 и более поздним версиям, а также к Windows Server 2008 R2 и более поздним версиям Windows.

Среда выполнения Direct3D использует следующий DDI Direct3D 11 для списков команд:

  • Функция CalcPrivateCommandListSize определяет размер частного региона драйвера отображения пользовательского режима для списка команд.

  • Функция CreateCommandList создает список команд.

  • Функция RecycleCommandList перезапускает список команд.

  • Функция RecycleCreateCommandList создает список команд и делает ранее неиспользуемый дескриптор DDI полностью допустимым.

  • Функция DestroyCommandList уничтожает список команд.

  • Функция RecycleDebaseCommandList уведомляет драйвер о том, что требуется упрощенное уничтожение списка команд.

  • Функция CommandListExecute выполняет список команд.

Семантика для функций CommandListExecute драйвера, CalcPrivateCommandListSize, CreateCommandList и DestroyCommandList в основном являются самообъявительными на основе других аналогичных функций DDI и документации ПО API для соответствующего DDI.

Когда среда выполнения Direct3D успешно вызывает функцию CreateCommandList или RecycleCreateCommandList в отложенном контексте, указанном в элементе hDeferredContext структуры D3D11DDIARG_CREATECOMMANDLIST , к которому указывает параметр pCreateCommandList , среда выполнения Direct3D выполняет следующую последовательность уничтожения в отложенном контексте:

  1. Среда выполнения Direct3D закрывает все открытые деферированные дескрипторы объектов. Обратите внимание, что эти дескрипторы по-прежнему могут быть привязаны к отложенному контексту.

  2. Время выполнения уничтожает отложенный контекст.

Во время вызова CreateCommandList или RecycleCreateCommandList все вызовы, которые драйвер выполняет в функции обратного вызова DDI с обновлением состояния , продолжают разглашать текущее состояние отложенного контекста. Однако при закрытии и уничтожении отложенного контекста все вызовы DDI обновления состояния отражают, что ничего не привязано (то есть сразу после вызова CreateCommandList или RecycleCreateCommandList все неявно несвязано).

Отложенный контекст может быть отменен либо явно приложением, либо вследствие ошибки API или драйвера. В таких случаях среда выполнения Direct3D выполняет следующую последовательность:

  1. Среда выполнения Direct3D вызывает функцию AbandonCommandList драйвера.

  2. Среда выполнения отменяет привязку дескрипторов из отложенного контекста один за другим.

  3. Среда выполнения закрывает все открытые отложенные дескрипторы объектов.

  4. Среда выполнения перезапускает или уничтожает отложенный контекст.

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

Во время вызова функции CommandListExecute драйвера драйвер должен перенести состояние отложенного контекста, чтобы сделать его эквивалентным состоянию при создании устройства. Эта операция также называется операцией сброса состояния. Однако во время вызова функции CommandListExecute драйвера все вызовы, которые драйвер выполняет в функции обратного вызова DDI с обновлением состояния, по-прежнему отражают состояние того, что было привязано во время последнего вызова DDI к функции драйвера. Во время следующего вызова функции DDI драйвера все вызовы, которые драйвер выполняет в функции обратного вызова DDI с обновлением состояния, показывают текущее состояние как полностью пустое, которое отражает неявный переход состояния из CommandListExecute. Этот факт немного отличается от типичной семантики и поведения функций обратного вызова DDI для обновления состояния. Если бы драйвер вызвал функцию обратного вызова DDI для обновления состояния во время вызова одной из функций SetShader драйвера, функция обратного вызова DDI для обновления состояния показала бы, что новый шейдер уже привязан. Это расхождение поведения обратного вызова DDI с обновлением состояния обеспечивает большую гибкость для драйвера, чтобы отразить старое состояние во время CommandListExecute.

API Direct3D версии 11 гарантирует, что запросы не были манипулированы (т. е. запросом QueryBegin или QueryEnd вызывается в нем) в списке команд и были "инициированы" только контекстом, который пытается выполнить список команд. API также гарантирует, что ни один список команд, созданный с использованием отображения динамического ресурса, не выполняется в контексте, где этот ресурс уже отображен. Прежде чем приложение вызывает функцию FinishCommandList, среда выполнения Direct3D вызывает функции QueryEnd и ResourceUnmap DDI драйвера для любого запроса или динамического ресурса, который всё ещё содержит начатый запрос или открытый сопоставленный ресурс, потому что FinishCommandList неявно завершает диапазоны запросов и снимает сопоставление с любого сопоставленного ресурса.

Оптимизация для небольших списков команд

Оптимизация перезапуска памяти для списков команд с небольшим объемом памяти может быть важной для уменьшения состязания между вызовами функций DDI списка команд и снижения затрат на обработку вызовов, необходимых для списков команд. Затраты на обработку, присущие каждому списку команд, являются значительными. Эта оптимизация предназначена для списков команд, в которых затраты на обработку, необходимые для списков команд, доминируют в пространстве ЦП и памяти, необходимом для списков команд. Список команд с небольшим объемом памяти— это, например, одна графическая команда, например CopyResource. Объем памяти, необходимый для CopyResource, составляет объем двух указателей. Однако CopyResource по-прежнему требует такой же объем обработки вызовов в списке команд, что и список команд большого объема памяти. Если списки команд с малым объемом памяти создаются часто, затраты на обработку, необходимые для выполнения вызова функций драйвера CreateCommandList, DestroyCommandList, CreateDeferredContext и DestroyDevice(D3D10) (в контексте отсроченного исполнения), становятся все более важными. Память, на которую ссылается здесь, — это системная память, содержащая структуры данных драйвера, которая включает в себя память для дескрипторов DDI.

Функция RecycleCommandList драйвера должна уведомить драйвер о том, когда дескрипторы драйверов выходят из использования (но еще не удалены), и когда ранее неиспользуемые дескрипторы драйверов повторно используются. Это уведомление относится как к дескрипторам списка команд, так и к дескрипторам отложенного контекста. Единственная память, которую драйвер должен освободить, — это память, на которую указывает дескриптор DDI. Хотя цель RecycleCommandList заключается в том, чтобы переработать память, связанную с этим дескриптором, для эффективности драйвер имеет полную свободу выбора памяти для переработки. Драйвер не может изменить размер области памяти, на которую указывает дескриптор списка команд непосредственного контекста. Этот размер — возвращаемое значение CalcPrivateCommandListSize. Драйвер также не может изменить размер области памяти, на которую указывает локальный дескриптор списка команд контекста. Этот размер является возвращаемым значением CalcDeferredContextHandleSize.

Функции DDI драйвера RecycleCreateCommandList и RecycleCreateDeferredContext должны возвращать коды ошибок нехватки памяти в виде значений HRESULT E_OUTOFMEMORY. Эти функции не предоставляют такие коды ошибок с помощью вызовов функции pfnSetErrorCb . Это требование драйвера предотвращает необходимость использования средой выполнения синхронизации на уровне устройства для отслеживания ошибок контекста в реальном времени, возникающих из этих функций драйвера, связанных с созданием. Наблюдение за этими ошибками будет источником катастрофических проблем для списков команд с небольшим объемом памяти.

Различия между функциями RecycleDecommandList драйвера, RecycleCommandList и RecycleCreateCommandList важны. К ним относятся следующие функции.

RecycleDestroyCommandList

Среда выполнения вызывает функцию RecycleDestroyCommandList драйвера, чтобы уведомить драйвер о необходимости упрощенного уничтожения. То есть драйвер пока не должен освобождать память для дескриптора списка команд DDI. Функция драйвера RecycleDestroyCommandList является свободной потоковой, как функция драйвера DestroyCommandList.

RecycleCommandList

Функция RecycleCommandList драйвера сообщает драйверу, что среда выполнения интегрировала дескриптор списка команд обратно в кэш отложенного контекста. Затем функция предоставляет драйверу возможность интегрировать память, связанную со списком команд обратно в кэш отложенного контекста. Среда выполнения вызывает функцию RecycleCommandList драйвера из отложенного контекстного потока. Функция DDI RecycleCommandList уменьшает необходимость в синхронизации со стороны самого драйвера.

RecycleCreateCommandList

Среда выполнения вызывает функцию RecycleCreateCommandList драйвера, чтобы сделать ранее неиспользуемый дескриптор DDI снова полностью действительным.

Эти функции DDI позволяют оптимизировать ресурсы для списков команд с небольшим объемом памяти. В следующем псевдокоде показана реализация среды выполнения через поток вызовов функций из API в DDI:

::FinishCommandList()
{
  // Empty InterlockedSList, integrating into the cache
  Loop { DC::pfnRecycleCommandList }

  If (Previously Destroyed CommandList Available)
 { IC::pfnRecycleCreateCommandList }
 else
  {
    IC::pfnCalcPrivateCommandListSize
    IC::pfnCreateCommandList
    IC::pfnCalcDeferredContextHandleSize(D3D11DDI_HT_COMMANDLIST)
  }

  Loop { DC::pfnDestroy* (context-local handle destroy) }

  IC::pfnRecycleCreateDeferredContext
}
...
Sporadic: DC::pfnCreate* (context-local open during first-bind per CommandList)

CommandList::Destroy()
{
  // If DC still alive, almost always recycle:
  If (DC still alive)
 { IC::pfnRecycleDestroyCommandList }
  Else
 { IC::pfnDestroyCommandList }
  // Add to InterlockedSList
}

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

Схема, иллюстрирующая состояния действительности дескриптора списка команд DDI непосредственного контекста.