지원 명령 목록

이 섹션은 Windows 7 이상 및 Windows Server 2008 R2 이상 버전의 Windows에만 적용됩니다.

Direct3D 런타임은 명령 목록에 다음 Direct3D 11 DDI를 사용합니다.

  • CalcPrivateCommandListSize 함수는 명령 목록에 대한 사용자 모드 표시 드라이버의 프라이빗 메모리 영역 크기를 결정합니다.

  • CreateCommandList 함수는 명령 목록을 만듭니다.

  • RecycleCommandList 함수는 명령 목록을 재활용합니다.

  • RecycleCreateCommandList 함수는 명령 목록을 만들고 이전에 사용하지 않은 DDI 핸들을 완전히 유효하게 만듭니다.

  • DestroyCommandList 함수는 명령 목록을 삭제합니다.

  • RecycleDestroyCommandList 함수는 명령 목록의 경량 소멸이 필요하다는 것을 드라이버에 알릴 수 있습니다.

  • CommandListExecute 함수는 명령 목록을 실행합니다.

드라이버의 CommandListExecute, CalcPrivateCommandListSize, CreateCommandList 및 DestroyCommandList 함수에 대한 의미 체계는 다른 유사한 DDI 함수 및 해당 DDI에 대한 API 설명서를 기반으로 대부분 자체 설명입니다.

Direct3D 런타임이 pCreateCommandList 매개 변수가 가리키는 D3D11DDIARG_CREATECOMMANDLIST 구조의 hDeferredContext 멤버에 지정된 지연된 컨텍스트에서 드라이버의 CreateCommandList 또는 RecycleCreateCommandList 함수를 성공적으로 호출한 후 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 콜백 함수의 일반적인 의미 체계 및 동작과 약간 다릅니다. 드라이버의 SetShader 함수 중 하나를 호출하는 동안 드라이버가 상태 새로 고침 DDI 콜백 함수를 호출한 경우 상태 새로 고침 DDI 콜백 함수는 바인딩되는 새 셰이더에 이미 바인딩된 것으로 표시됩니다. 이러한 상태 새로 고침 DDI 콜백 동작의 차이는 CommandListExecute 중에 이전 상태를 반영하도록 드라이버에 더 많은 유연성을 제공합니다.

Direct3D 버전 11 API는 명령 목록에 의해 쿼리가 조작되지 않았으며(즉, QueryBegin 또는 QueryEnd가 호출됨) 명령 목록을 실행하려는 컨텍스트에 의해서만 "시작"되었는지 확인합니다. 또한 API는 동적 리소스의 맵을 기록한 명령 목록이 현재 매핑된 동일한 리소스가 있는 컨텍스트에서 실행되지 않도록 합니다. 애플리케이션이 FinishCommandList 함수를 호출하기 전에 Direct3D 런타임은 FinishCommandList가 쿼리 범위를 암시적으로 종료하고 매핑된 리소스의 매핑을 해제하기 때문에 시작 쿼리 또는 매핑된 리소스가 열려 있는 모든 쿼리 또는 동적 리소스에서 드라이버의 QueryEnd 및 ResourceUnmap DDI 함수를 호출합니다.

작은 명령 목록에 대한 최적화

메모리 양이 적은 명령 목록에 대한 메모리 재활용 최적화는 명령 목록 DDI 함수 호출 간의 경합을 줄이고 명령 목록에 필요한 호출 처리 오버헤드를 줄이는 것이 중요할 수 있습니다. 각 명령 목록에 내재된 처리 오버헤드는 중요합니다. 이 최적화는 명령 목록에 필요한 처리 오버헤드가 명령 목록에 필요한 CPU 시간과 메모리 공간을 지배하는 명령 목록을 위한 것입니다. 작은 메모리 크기 명령 목록은 예를 들어 CopyResource와 같은 단일 그래픽 명령입니다. CopyResource에 필요한 메모리 양은 두 포인터입니다. 그러나 CopyResource에는 대용량 명령 목록과 동일한 양의 명령 목록 호출 처리가 여전히 필요합니다. 메모리 양이 적은 명령 목록이 높은 빈도로 생성되면 런타임에서 드라이버의 CreateCommandList, DestroyCommandList, CreateDeferredContextDestroyDevice(D3D10) 함수(지연된 컨텍스트)를 호출하는 데 필요한 처리 오버헤드가 점점 더 중요해지고 있습니다. 여기에 언급된 메모리는 DDI 핸들에 대한 메모리를 포함하는 드라이버 데이터 구조를 보유하는 시스템 메모리입니다.

드라이버의 RecycleCommandList 함수는 드라이버 핸들이 사용되지 않고(아직 삭제되지 않음) 이전에 사용되지 않은 드라이버 핸들이 다시 사용되는 경우 드라이버에 알려야 합니다. 이 알림은 명령 목록 및 지연 컨텍스트 핸들 모두에 적용됩니다. 드라이버가 재활용해야 하는 유일한 메모리는 DDI 핸들이 가리키는 메모리입니다. RecycleCommandList목적은 핸들과 연결된 메모리를 재활용하는 것이지만 효율성을 위해 드라이버는 재활용할 메모리를 선택하고 선택할 수 있는 완전한 유연성을 제공합니다. 드라이버는 직접 컨텍스트 명령 목록이 가리키는 메모리 영역의 크기를 변경할 수 없습니다. 이 크기는 CalcPrivateCommandListSize반환 값입니다. 또한 드라이버는 컨텍스트 명령이 로컬 핸들을 가리키는 메모리 영역의 크기를 변경할 수 없습니다. 이 크기는 CalcDeferredContextHandleSize반환 값입니다.

드라이버의 RecycleCreateCommandListRecycleCreateDeferredContext DDI 함수는 메모리 부족 오류 코드를 E_OUTOFMEMORY HRESULT 값으로 반환해야 합니다. 이러한 함수는 pfnSetErrorCb 함수에 대한 호출을 통해 이러한 오류 코드를 제공하지 않습니다. 이 드라이버 요구 사항은 런타임이 디바이스 전체 동기화를 사용하여 이러한 만들기 형식 드라이버 함수의 즉각적인 컨텍스트 오류를 감시할 필요가 없도록 합니다. 이러한 오류를 감시하는 것은 메모리 양이 적은 명령 목록에 치명적인 경합의 원인입니다.

드라이버의 RecycleDestroyCommandList, RecycleCommandListRecycleCreateCommandList 함수 간의 차이점이 중요합니다. 해당 기능에는 다음이 포함되어 있습니다.

RecycleDestroyCommandList

런타임은 드라이버의 RecycleDestroyCommandList 함수를 호출하여 경량 소멸이 필요하다는 것을 드라이버에 알립니다. 즉, 드라이버는 DDI 명령 목록 핸들에 대한 메모리를 아직 할당 해제하지 않아야 합니다. 드라이버의 RecycleDestroyCommandList 함수는 드라이버의 DestroyCommandList 함수와 마찬가지로 자유 스레드입니다.

RecycleCommandList

드라이버의 RecycleCommandList 함수는 런타임이 명령 목록 핸들을 지연된 컨텍스트 캐시에 다시 통합했음을 드라이버에 알릴 수 있습니다. 그런 다음 이 함수는 명령 목록과 연결된 메모리를 지연된 컨텍스트 캐시에 다시 통합할 수 있는 기회를 드라이버에 제공합니다. 런타임은 지연된 컨텍스트 스레드에서 드라이버의 RecycleCommandList 함수를 호출합니다. RecycleCommandList DDI 함수를 사용하면 드라이버가 자체 동기화를 수행할 필요가 줄어듭니다.

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 명령 목록 핸들의 유효성 상태를 보여 주는 다이어그램