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


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

Этот раздел относится только к 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 драйвера для любого запроса или динамического ресурса, который по-прежнему содержит открытый запрос или сопоставленный ресурс, так как ГотовоCommandList неявно завершает диапазоны запросов и не сопоставляет любой сопоставленный ресурс.

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

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

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

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

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

RecycleDeskCommandList

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