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

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

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

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

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

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

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

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

  • Функция RecycleDe соответствииCommandList уведомляет драйвер о необходимости легкого удаления списка команд.

  • Функция 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 вызывает функцию DDI драйвера QueryEnd и ResourceUnmap для любого запроса или динамического ресурса, который по-прежнему содержит открытый начатый запрос или сопоставленный ресурс, так как FinishCommandList неявно завершает диапазоны запросов и отменяет сопоставление всех сопоставленных ресурсов.

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

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

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

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

Важное значение имеют различия между функциями RecycleDebaseCommandList, RecycleCommandList и RecycleCreateCommandList . Их функции включают следующие.

RecycleDeкистрояCommandList

Среда выполнения вызывает функцию RecycleDeкистрояCommandList драйвера, чтобы уведомить драйвер о необходимости легкого уничтожения. То есть драйвер пока не должен отменять выделение памяти для дескриптора списка команд DDI. Функция RecycleDeкистраторCommandList драйвера работает в свободном потоке так же, как функция 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 непосредственного контекста.