다음을 통해 공유


자동 디스플레이 스위치

중요하다

일부 정보는 상용 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보와 관련하여 명시적이거나 묵시적인 보증을 하지 않습니다.

이 문서에서는 iGPU(통합 GPU)와 dGPU(불연속 GPU) 간에 원활하게 전환할 수 있도록 노트북의 내부 패널을 지원하는 ADS(자동 디스플레이 스위치) 기능에 대해 설명합니다. ADS는 Windows 11 버전 24H2 업데이트 2025.01D(WDDM 3.2)부터 지원되는 선택적 WDDM 기능입니다.

이 기사에서는

  • GPU0은 통합 패널이 현재 연결되어 있는 GPU를 나타냅니다.
  • GPU1은 패널을 전환할 GPU를 나타냅니다.

개요

출시된 일부 노트북에는 iGPU(통합 GPU)와 dGPU(불연속 GPU) 간에 내부 패널을 전환할 수 있는 멀티플렉서(mux) 디바이스가 있습니다. 그래픽 드라이버는 현재 OS의 개입 없이 이러한 노트북에서 전환을 실행하므로, 사용자 경험에 있어 부정적인 영향을 미칠 수 있습니다.

ADS를 사용하면 OS가 내부 패널에 디스플레이 신호를 전송할 때 시스템에서 mux 디바이스 사용을 제어하여 iGPU와 dGPU 사이를 전환할 수 있습니다. 따라서 OS는 더 나은 사용자 환경을 제공할 수 있습니다.

ADS의 초기 버전은 iGPU와 dGPU 간에 내부 패널 전환만 지원합니다. 향후에는 노트북에서 외부 커넥터의 muxing을 지원하도록 이 기능이 확장될 수 있습니다.

높은 수준의 디자인

일반적으로 시스템은 스위치가 진행되는 동안 깜박임/결함 없이 내부 패널의 콘텐츠가 표시되는지 확인해야 합니다. OS는 이 기능을 특정 표시 프로토콜로 제한하지 않습니다. 이 문서에서는 eDP를 사용하여 ADS를 구현하는 방법을 중시하지만 사용할 수 있는 더 많은 업계 표준(예: MIPI 또는 DSI)이 있습니다. 플랫폼 디자인은 다른 OS 변경 없이 동일한 환경을 달성할 수 있는 경우 다른 디스플레이 연결 프로토콜을 자유롭게 사용할 수 있습니다.

이 섹션 내의 하위 섹션은 기능의 디자인 측면을 식별하고 각 측면에 대한 높은 수준의 접근 방식을 자세히 설명합니다.

mux 장치 제어

iGPU 및 dGPU 그래픽 드라이버 간의 종속성을 줄이기 위해 mux는 OS가 그래픽 드라이버와 독립적으로 제어할 수 있는 별도의 디바이스로 노출됩니다. 이 방법의 장점은 다음과 같습니다.

  1. 드라이버가 OEM에서 사용할 수 있는 모든 다른 mux를 제어하는 방법을 알 필요가 없으므로 그래픽 드라이버의 복잡성을 줄입니다.
  2. 그래픽 드라이버 간의 종속성을 줄이거나 제거하므로 드라이버 업데이트가 줄어들고 OEM에서 GPU 및 muxe를 더 쉽게 선택할 수 있습니다.
  3. 그래픽 드라이버를 사용할 수 없는 경우 OS에서 mux를 전환할 수 있습니다.

mux 장치 공개

이 솔루션은 내부 iGPU와 dGPU 간의 muxing용이므로 ACPI를 통해 mux를 노출하는 것이 좋습니다.

mux 드라이버의 기능

mux 드라이버는 다음과 같은 높은 수준의 기능 요구 사항을 충족해야 합니다.

  1. mux의 상태, 현재 내부 패널을 제어하는 대상, 및 모든 기능 제한을 제공해야 합니다.
  2. 스위치를 트리거하고 스위치의 상태를 보고하는 방법을 제공해야 합니다.

mux ACPI 디바이스 및 해당 메서드에 대한 자세한 내용은 ACPI참조하세요.

원활한 스위치를 수행하기 위해 mux 디바이스에는 GPU 스위치 중에 항상 다음 조건이 필요합니다.

  1. 패널 전원. 항상 mux는 GPU 중 하나에서 패널 전원이 공급되어야 합니다. 두 GPU가 동시에 패널 전원을 제공해도 됩니다.
  2. 두 GPU 모두 전환 시 밝기가 활성화된 제어 신호입니다.
  3. 전환 시 두 GPU의 밝기 수준(펄스 너비 변조)

mux는 두 GPU와 패널 간에 다음 정보를 전환합니다.

  1. 밝기를 조정하는 제어 신호
  2. 밝기 수준(펄스 너비 변조)
  3. DisplayPort(DP) 보조 라인
  4. HPD(핫 플러그 감지) 라인
  5. DP 데이터 줄

mux에는 패널이 활성화되지 않은 경우 전환할 수 있는 기능이 있어야 합니다. 내부 패널 전환 시에는 적어도 mux가 전환할 때 GPU에 HPD 신호를 보내지 말아야 합니다.

GPU 드라이버는 mux ACPI 메서드를 호출해서는 안 됩니다.

자동 디스플레이 스위치 DDI

mux 요구 사항을 충족하기 위해 여러 DDI가 추가됩니다. 다음 함수를 사용하여 OS가 mux 스위치 중에 드라이버의 DDI를 호출하는 5가지 지점이 있습니다. 다양한 호출은 스위치의 단계와 드라이버가 현재 디스플레이를 제어하는 GPU를 제어하는지 여부에 따라 달라집니다.

DDI 설명
DxgkDdiDisplayMuxPreSwitchAway 현재 디스플레이에 연결된 드라이버를 호출합니다. 이 호출은 시스템에서 디스플레이를 다른 GPU(GPU0에서 GPU1로)로 전환할 계획임을 드라이버에 알릴 수 있습니다.
DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData 현재 패널에 연결된 드라이버(GPU0)에서 프라이빗 스위치 데이터를 수집하도록 호출합니다.
DxgkDdiDisplayMuxPreSwitchTo 현재 디스플레이에 연결되지 않은 드라이버에 대한 호출입니다. 이 호출은 OS가 디스플레이를 이 GPU(GPU1)로 전환할 계획임을 드라이버에 알릴 수 있습니다.
DxgkDdiDisplayMuxSwitchCanceled 스위치가 완료되기 전에 스위치 시퀀스가 취소되었음을 나타내기 위해 드라이버를 호출합니다.
DxgkDdiDisplayMuxPostSwitchAway mux 스위치가 완료되고 GPU0의 드라이버가 더 이상 디스플레이에 연결되지 않습니다.
DxgkDdiDisplayMuxPostSwitchToPhase1 mux 스위치가 완료되고 GPU1의 드라이버가 디스플레이에 연결되었습니다. 이제 이 드라이버는 1단계 작업을 수행해야 합니다.
DxgkDdiDisplayMuxPostSwitchToPhase2 mux 스위치가 완료되고 GPU1의 드라이버가 디스플레이에 연결되었습니다. 이제 이 드라이버는 2단계 작업을 수행해야 합니다.
DxgkDdiDisplayMuxUpdateState 어댑터 시작 시 호출되고 D0 전원 상태로 돌아가서 드라이버가 현재 mux 상태를 알 수 있도록 합니다.

드라이버가 각 단계에서 완료해야 하는 명시적 작업이 있습니다. 이러한 작업은 이 문서의 뒷부분에 설명되어 있습니다.

ADS 관련 DDI 업데이트의 전체 목록은 자동 디스플레이 전환에 대한 WDDM DDI 변경을 참조하세요.

GPU0과 GPU1 간에 데이터 공유

다음과 같은 경우에 더 나은 사용자 환경을 빌드할 수 있는 경우가 있을 수 있습니다.

  • GPU0 및 GPU1은 동일한 IHV에서 제공됩니다.
  • GPU0는 OS에 불투명한 표시 구성과 관련된 정보를 GPU1에 전달할 수 있습니다.

데이터 블롭은 GPU1의 드라이버가 이를 이해할 경우 신속하게 식별할 수 있는 GUID로 설명됩니다. 높은 수준에서 OS는 GPU0을 호출하여 스위치 전에 Blob GUID 및 데이터를 가져와서 디스플레이의 HPD에 요청하기 전에 GPU1에 전달합니다.

GPU1의 드라이버는 다음을 담당합니다.

  • Blob의 GUID를 이해하는지 확인합니다.
  • Blob에서 잘못된 형식의 데이터로 인한 유해한 영향을 방지하기 위해 Blob의 각 데이터 요소의 유효성을 검사합니다.

드라이버 상호 운용성

WDDM 드라이버가 ADS를 지원하는 경우 실행 중인 OEM 시스템이나 시스템의 다른 GPU에 관계없이 ADS를 지원해야 합니다.

스위치 시퀀스

GPU의 드라이버가 중지될 때 기술적으로 GPU에서 전환할 수 있지만 이 시나리오는 현재 지원되지 않습니다. 따라서 스위치는 두 GPU에 전환 DDI를 지원하는 드라이버가 로드된 경우에만 수행됩니다.

다음 시퀀스는 패널이 활성화된 경우 전체 스위치 시퀀스의 상위 수준 보기이며, GPU0 및 GPU1은 각각 iGPU 및 dGPU를 나타냅니다. GPU0은 현재 멀티플렉서를 통해 내부 패널에 연결되어 있으며 GPU1로 전환하여 패널로 전송하려고 합니다.

  1. 스위치 호출은 API 수준에서 이루어집니다.
  2. OS는 현재 내부 패널 상태(HDR, 모드, 새로 고침 속도 등)의 특성을 수집하고 임시 디스플레이 모드를 확인합니다.
  3. OS는 시스템의 어떤 GPU에서 발생하는 HPD로 인해 어떤 표시 토폴로지도 수행할 수 없도록 비활성화합니다.
  4. OS는 GPU1 드라이버의 DxgkDdiDisplayMuxPreSwitchTo호출하여 현재 밝기 수준을 전달합니다. 드라이버는 뚜껑이 열려 있는 경우에만 다음을 수행해야 합니다.
    • 패널에 전원을 켭니다.
    • 밝기 활성 신호를 설정합니다.
    • OS가 통과한 밝기 수준을 설정합니다.
  5. OS는 mux 스위치 전까지 GPU0에서 DxgkDdiQueryConnectionChange 호출을 사용할 수 없게 설정하여 뚜껑 HPD 처리가 이루어지지 않도록 합니다.
  6. OS는 GPU0 드라이버의 DxgkDdiDisplayMuxPreSwitchAway DDI를 호출합니다. 드라이버는 다음을 수행해야 합니다.
    • 뚜껑이 활성화된 경우 패널에서 PSR1(패널 자체 새로 고침 1)을 사용하도록 설정하고, OS가 시퀀스 후반부에 비활성화를 요청할 때까지 이를 유지합니다.
    • DXGK_CONNECTION_CHANGEConnectionStatus monitorStatusDisconnected 설정하고 MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange 1로 설정된 연결 변경 목록에 패킷을 추가합니다.
    • GPU0는 뚜껑 대상에 대한 연결 변경 패킷을 큐에 추가할 수 없습니다. OS 버그는 그렇게 하는지 확인합니다.
    • 프라이빗 ADS 데이터 블롭(GUID 및 데이터)의 크기를 운영 체제에 반환합니다. GPU0 드라이버가 이 호출에 실패하는 경우 반환하기 전에 큐에 배치된 ADS 연결 상태 패킷이 제거되었는지 확인해야 합니다.
  7. GPU0 드라이버가 0이 아닌 개인 데이터 크기를 반환하는 경우 OS는 해당 크기를 할당하고 GPU0의 DxgkDdiDisplayMuxPreSwitchAwayGetPrivateData 콜백에 전달하여 프라이빗 스위치 데이터를 가져옵니다.
  8. OS는 mux의 ACPI 메서드를 호출하여 GPU0에서 GPU1로 전환합니다.
  9. OS는 GPU0의 DxgkDdiQueryConnectionChange을 다시 호출할 수 있도록 합니다.
  10. OS는 GPU0의 DxgkDdiQueryConnectionChanges 호출하여 DisplayMuxConnectionChange가 1로 설정된 MonitorStatusDisconnected 연결 패킷을 처리합니다.
  11. OS는 GPU0의 DxgkddiSettimingsfromvidpn를 호출하여 전환 중인 디스플레이의 경로를 비활성화합니다. GPU0 드라이버는 다음을 수행해야 합니다.
    • 패널 전원을 끕니다.
    • 밝기 신호를 사용하지 않도록 설정합니다.
    • mux에 밝기 수준 전송을 중지합니다.
  12. OS는 디스플레이 출발을 처리합니다. 불필요한 토폴로지 변경을 방지하기 위해 토폴로지 변경을 트리거하지 않습니다.
  13. OS는 GPU1의 DxgkDdiDisplayMuxPostSwitchToPhase1 콜백을 호출하여 GPU0에서 가져온 ADS 프라이빗 블롭을 전달합니다. 드라이버는 다음을 수행해야 합니다.
    • 뚜껑이 열려 있는지 또는 닫혀 있는지 확인합니다.
    • DXGK_CONNECTION_CHANGE사용하여 해당 연결 변경 목록에 패킷을 추가합니다.
      • MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange 비트가 설정됩니다.
      • ConnectionStatus 뚜껑이 열려 있으면 MonitorStatusConnected로 설정되고, 뚜껑이 닫혀 있으면 MonitorStatusDisconnected로 설정됩니다.
    • 뚜껑이 닫히면, 패널로의 전원과 밝기 신호를 끕니다.
  14. OS가 아직 GPU1의 내부 대상에 대해 DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2을 사용하여 DxgkDdiQueryAdapterInfo을 호출하지 않은 경우, 이를 수행합니다. 이 호출의 결과로 OS는 DxgkDdiQueryDeviceDescriptor 호출합니다.
  15. OS는 GPU1의 DxgkDdiQueryConnectionChange 호출하여 연결 변경 목록에서 이벤트를 처리합니다. 이 호출로 인해 DxgkDdiQueryDeviceDescriptor HPD'ed인 새 모니터에 대해 호출됩니다.
  16. OS를 사용하면 HPD로 인한 표시 토폴로지 변경이 가능합니다.
  17. OS는 DisplayMuxConnectionChange이 1로 설정된 상태에서 GPU0 및 GPU1의 연결 패킷을 비동기적으로 처리합니다.
  18. GPU1이 MonitorStatusConnected대기할 경우:
    • OS는 GPU1의 DWM 함수를 호출하여 모드를 열거합니다.
    • DxgkddiSettimingsfromvidpn GPU1에서 호출되어 표시 경로를 활성화합니다.
    • DWM은 GPU1의 표시 경로에 프레임을 렌더링하고 표시합니다.
    • OS는 첫 번째 프레임이 표시될 때까지 기다립니다.
  19. OS는 GPU1의 DxgkDdiDisplayMuxPostSwitchToPhase2 콜백을 호출합니다. 이때, 만약 MonitorStatusConnected가 GPU1에 의해 큐에 대기된 경우, 드라이버는 디스플레이의 PSR1을 비활성화해야 합니다. 그렇지 않으면 아무 작업도 수행하지 않습니다.
  20. OS가 GPU0의 DxgkDdiDisplayMuxPreSwitchAway를 호출합니다. 드라이버에서 기대되는 작업은 없지만, 이 호출은 전환과 관련된 모든 드라이버 정리 또는 기록 작업에 유용합니다.
  21. OS는 현재 내부 패널 상태의 특성을 수집합니다. 패널 상태가 이전에 저장한 것과 다른 경우 OS는 원격 분석을 트리거합니다.

이 스위치 시퀀스는 iGPU->dGPU 및 dGPU>iGPU와 동일합니다. 패널이 비활성 상태일 때 mux를 전환하는 경우가 있을 수 있습니다. 이 경우 이 시퀀스는 필요하지 않으며 OS는 mux에서 ACPI 메서드를 호출하여 전환할 수 있습니다.

대부분의 OS는 드라이버가 PSR 모드에 있는지 알지 못합니다. 따라서 사용자에게 이러한 일이 보이지 않더라도 드라이버는 여전히 Vsync 동기화를 생성하고, 화면 플립을 완료된 것으로 보고하는 등의 작업을 수행해야 합니다.

복구 프로세스

스위치 시퀀스의 모든 단계에서 오류가 발생하면 다음 정리가 수행됩니다.

  1. OS는 GPU0의 DxgkDdiDisplayMuxPreSwitchAway 호출이 성공적으로 이루어졌지만, 그 후속 조치인DxgkDdiDisplayMuxPostSwitchAway 호출이 이루어지지 않은 경우 GPU0의 DxgkDdiDisplayMuxSwitchCanceled를 호출합니다.
  2. 만약 GPU1의 DxgkDdiDisplayMuxPreSwitchTo가 성공적으로 호출되었고, 그 다음에 DxgkDdiDisplayMuxPostSwitchToPhase2가 호출되지 않은 경우, OS는 GPU1의 DxgkDdiDisplayMuxSwitchCanceled을 호출합니다.
  3. OS는 비활성화된 경우 표시 토폴로지 변경 내용을 다시 사용하도록 설정합니다.
  4. OS는 사용하지 않도록 설정된 경우 GPU0에서 DxgkDdiQueryConnectionChange 호출을 다시 사용하도록 설정합니다.
  5. OS는 뚜껑이 연결된 GPU에서 뚜껑 연결 상태를 확인합니다.
  6. 운영 체제가 표시 설정 구성(SDC) 재설정을 트리거합니다. mux를 통해 패널이 연결된 드라이버(DxgkDdiDisplayMuxSwitchCanceled반환됨)는 PSR을 사용하지 않도록 설정해야 합니다.

전환 중에 발생할 수 있는 비정상적인 이벤트

  • 사용자 모니터를 외부 플러그에 연결하거나 분리

    스위치 시퀀스의 일부로 OS의 HPD 이벤트 처리를 사용하지 않도록 설정합니다. 이러한 방식으로 모든 HPD는 뚜껑 도착 시 함께 대기하고 처리되어 하나의 원자적 작업으로 진행됩니다.

  • 다른 앱은 스위치 중에 SDC를 호출합니다.

    스위치가 진행 중인 동안 SDC에 대한 호출이 차단되고 스위치가 처리된 후 실행됩니다.

  • 스위치를 전환할 때 드라이버가 비활성화됩니다.

    드라이버가 중지되면 스위치 시퀀스의 호출이 실패하고 복구 시퀀스가 활성화됩니다. PnPStop 섹션 화면이 항상 표시되는지 확인하는 방법도 자세히 설명합니다.

뚜껑 닫기 시나리오

드라이버는 일반적으로 다음 방법 중 어느 것을 사용하여 뚜껑 열기/닫기 이벤트를 감지할 수 있습니다.

그러나 일반적으로 WDDM의 경우 드라이버는 Dxgkrnl 상태 및 드라이버 상태를 동기화할 수 있으므로 DxgkDdiNotifyAcpiEvent 접근 방식을 사용해야 합니다. iGPU와 dGPU가 모두 스위치 시퀀스에서 GPU1일 수 있다는 점을 감안할 때 모든 ADS 드라이버가 뚜껑을 멀리 전환한 경우에도 뚜껑 상태를 추적하는 것이 좋습니다.

OS가 GPU0에서 DisplayMuxConnectionChange 이벤트를 처리하면 GPU0가 더 이상 뚜껑 상태를 소유하지 않으므로 GPU0은 뚜껑이 다시 전환될 때까지 해당 대상에 대한 연결 상태 패킷을 더 이상 보고할 수 없다고 간주합니다. GPU0에서 이 작업을 수행하는 경우 OS는 버그 검사를 수행합니다. 일단 OS가 GPU1에서 DisplayMuxConnectionChange을 처리하면, GPU1이 뚜껑 상태의 소유자로 간주됩니다. GPU1이 뚜껑 상태를 알고 올바른 DisplayMuxConnectionChange 패킷을 보고해야 함에 따라 뚜껑 열기 또는 닫기 이벤트는 이러한 두 이벤트 간에 무시될 수 있습니다.

OS에서 드라이버가 패널을 소유한다고 간주하는 경우

다음 표에서는 OS가 패널을 소유하도록 GPU를 고려하는 시퀀스 단계를 설명합니다. 소유 GPU는 스위치 시퀀스를 사용하여 연결 변경 내용을 보고할 수 있습니다. 단계 번호는 이전에 설명한 스위치 시퀀스에서 가져옵니다.

스테이지에서 스테이지 에서 패널 제어하는 GPU
전환 전 5단계 GPU0
6단계 12단계 GPU 없음
13단계 전환 후 GPU1

OS 버그는 GPU가 패널을 제어하지 않을 때 드라이버 큐에서 멀티플렉싱된 대상의 연결 변경 패킷이 나타나는지 검사합니다.

패널 자체 새로 고침(PSR) 제어

ADS 기능은 PSR을 사용하여 전환 중에 결함을 방지합니다. 특히, GPU0 및 GPU1에서 사용할 PSR 모드를 협상할 필요가 없도록 PSR1(전체 화면 업데이트 모드)이 사용됩니다.

PSR1 내에서도 패널에서 지원해야 하는 선택적 기능이 있습니다.

싱크 기능 세부 정보 은/는을/를 통해 노출됨
DPCD & eDP 버전 eDP v1.3 이상을 노출하십시오. DPCD
PSR 기능 및 버전 싱크는 버전 1을 지원할 것입니다. DPCD 00070h 비트 7:0
PSR 상태를 전달하는 VSC SDP 지원 PSR에만 해당; 싱크 장치는 최소한 수정 버전 2를 지원해야 하며 PSR 상태와 CRC 값을 전달하기 위해 최대 8바이트를 처리할 수 있어야 합니다. DPCD 170
싱크는 PSR 관련 상태를 정확하게 보고해야 합니다. 싱크는 상태를 노출해야 하며, 예를 들어 링크 CRC 오류, RFB 스토리지 오류, 싱크 디바이스 자체 새로 고침 상태, 최대 재동기 프레임 수, 싱크에서의 마지막 실제 동기화 지연 시간 및 마지막으로 받은 PSR SDP가 이에 해당합니다. DPCD 2008h, 2009h, 200Ah는 싱크의 올바른 상태를 반영해야 합니다.

GPU1이 OS에서 DxgkddiSettimingsfromvidpn 호출의 일부로 링크 학습을 수행하는 경우 드라이버는 GPU0에서 사용하는 DP 레인 및 대역폭 설정을 모르므로 빠른 링크 학습보다는 전체 링크 학습 시퀀스를 수행해야 합니다. OS는 GPU 간에 PSR 정책을 협상하지 않으므로 패널은 GPU에서 사용할 모든 PSR 버전 및 기능을 지원해야 합니다. 예를 들어, 패널은 GPU0이 일부 기능 집합으로 PSR2를 사용할 수 있는 시나리오를 지원해야 하고, 그 다음 PSR1이 전환에 사용되며, 이후 GPU1이 다른 기능 집합으로 PSR2를 사용할 수 있는 시나리오가 필요합니다.

스위치 중에 패널이 PSR에 유지되도록 보장

GPU1이 패널에서 모드를 설정하는 경우 패널이 PSR에 있는 동안 GPU1에서 설정한 링크 특성이 PSR 엔트리 모드와 일치한다는 보장은 없습니다. 예를 들어 새로 고침 속도 또는 활성 크기가 변경될 수 있습니다. 현재 DP 또는 기타 업계 표준은 연결 특성이 변경되는 동안 패널을 PSR에 유지할 수 있다고 패널이 보고할 수 있는 방법이 없습니다. 장기적으로 이 기능을 DP 사양에 추가하려고 합니다. 이렇게 될 때까지 ADS 사용 시스템의 경우 OEM은 PSR에 유지할 수 있는 TCon/panel/Mux 조합을 선택해야 하며 링크 특성(예: 새로 고침 속도, 활성 크기)은 EDID에 노출된 두 조합 간에 변경됩니다. 이 방법을 사용하면 스위치 중에 PSR을 활성 상태로 유지할 수 있습니다.

ADS HLK 테스트가 전환 과정에서 PSR의 유지를 확인할 수 있도록 GPU1이 모드를 테스트한 후 PSR이 활성 상태가 아니었음을 운영체제가 알 수 있는 방법이 필요합니다. 문제는 연결 학습에서 PSR을 지원할 수 없는 경우 패널이 어떻게 반응할지 정의되지 않았다는 것입니다.

DxgkDdiDisplayMuxPostSwitchToPhase2일부로 드라이버는 패널이 PSR에 없음을 감지했는지 여부를 OS에 알리기 위해 pWasPanelInPSR에서 부울 값을 반환합니다.

내부 패널의 EDID

OS가 디스플레이 모드 및 서로 다른 모니터가 연결된 토폴로지 선택 시 예상되는 동작을 제공하려면 내부 디스플레이에 대한 EDID/DisplayId를 보고하려면 두 GPU가 모두 필요합니다. 이 요구 사항은 디스플레이 모드 및 토폴로지 저장 CCD 데이터베이스가 내부 디스플레이를 제어하는 GPU와 관계없이 동일한 설정을 선택하도록 합니다.

드라이버가 OS에 보고하는 EDID는 수정 없이 aux 명령을 사용하여 패널에서 쿼리되는 EDID여야 합니다.

현재 OS는 내부 패널을 보고하는 드라이버를 시작할 때 DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2)를 호출합니다. mux가 해당 통합 대상에서 벗어난 경우, 드라이버는 패널과 통신하여 필요한 정보를 수집할 수 없습니다. 해결 방법은 드라이버가 시작되고 mux가 내부 대상에서 멀리 전환되면 OS가 DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2) 호출을 지연하여 mux가 내부 대상으로 처음 전환될 때까지 지연된다는 것입니다.

OS가 시스템에서 ADS 기능이 활성화되었는지 여부와 전환이 허용되는지를 결정하는 방법

OS는 다음 검사 목록을 수행하여 시스템에서 ADS를 사용할 수 있는지 확인합니다. ADS가 지원되려면 모든 검사가 참이어야 합니다.

  1. 통합 하이브리드로 표시된 GPU(DXGK_DRIVERCAPS.HybridIntegrated)가 다음을 수행합니다:
  2. 불연속 하이브리드(DXGK_DRIVERCAPS.HybridDiscrete)로 표시된 GPU가 있습니다. 이 GPU는 다음을 수행합니다.
  3. 1단계와 2단계에서 ACPI DMID 메서드에서 반환된 mux ACPI 이름이 일치합니다.
  4. ACPI mux 디바이스에는 ACPI DMQU, DMCF 및 DMSL 메서드가 있습니다.
  5. GPU 중 하나에서 mux ACPI DMQU 메서드가 내부 패널 대상의 ACPI 이름을 반환했습니다.
  6. ADS는 현재 단일 내부 패널이 있는 시스템만 지원합니다.
  7. 둘 중 하나:
    1. GPU0, GPU1 및 Mux ACPI는 모두 전체 ADS 지원을 보고합니다.
    2. GPU0, GPU1 및 Mux ACPI는 모두 실험적 또는 전체 ADS 지원을 보고하며 EnableMDMExperimentalFeature 레지스트리 키가 설정됩니다.

조건 1과 2는 mux를 전환하기 위해 두 어댑터를 모두 시작해야 함을 의미합니다.

ADS 기능 출시 품질 제어

ADS가 좋은 사용자 환경을 제공하려면 다음 구성 요소가 모두 완벽하게 함께 작동해야 합니다.

  1. OS는 mux 기능을 표시합니다.
  2. mux 전환을 위한 플랫폼 ACPI 메서드입니다.
  3. iGPU 및 dGPU 드라이버의 디스플레이 mux 전환 기능입니다.

IHV/OEM이 릴리스에서 비직선 품질 코드를 사용할 수 있도록 하기 위해 다음과 같은 수준의 ADS 지원을 노출할 수 있습니다.

  • 지원 없음: 드라이버는 ADS 기능을 지원하지 않습니다.
  • 개발 지원: 드라이버는 ADS를 지원하지만 드라이버의 구현은 아직 개발 중이며 이 용도 이상으로 사용하면 안 됩니다.
  • 실험적 지원: 드라이버는 ADS를 지원하지만 아직 출하 품질에는 도달하지 못했습니다. OS는 기본적으로 ADS를 사용하도록 설정하지 않지만 사용하도록 구성할 수 있습니다.
  • 완전한 지원: 드라이버는 출하 품질 수준에서 ADS를 지원합니다. OS는 드라이버가 ADS를 지원한다고 간주합니다.

디스플레이 스위치 후 동일하게 유지해야 하는 표시 특성

디스플레이 스위치는 다음 표시 특성을 변경하지 않아야 합니다.

  1. 데스크톱 해상도
  2. VidPn 경로(VidPn 소스 모드, 대상 모드, 크기 조정 등 포함)
  3. DPI
  4. 야간 조명 설정
  5. 감마
  6. 디스플레이 구성
  7. HDR 켜기/끄기
  8. SDR 흰색 수준
  9. 색상 프로파일
  10. 모니터의 OPM 대상 유형
  11. 디스플레이 밝기

원활한 전환 경험을 위한 GPU 기능 일치

사용자에게 원활한 전환 환경을 제공하려면 스위치 이전과 동일한 스위치 후에 디스플레이를 구성해야 합니다. 이 동작을 달성하기 위해 두 GPU 모두 동일한 지원이 필요한 특정 GPU 기능이 있습니다. 예를 들어, 한 GPU가 HDR을 지원하고 다른 GPU가 지원하지 않는 경우, HDR이 활성화된 상태에서의 전환은 원활하지 않을 것입니다.

다음 표에서는 GPU 표시 기능 및 기능을 나열하고 두 GPU 간의 맞춤 요구 사항을 설명합니다.

기능 원활한 지원 필요한 GPU
HDR 패널에서 HDR을 지원하는 경우, 두 GPU가 모두 fp16 HDR을 지원하거나 둘 다 HDR을 지원하지 않아야 합니다.
Hw 커서 아니요. OS는 사용자에게 방해가 되지 않도록 다양한 커서 기능에 적응합니다.
MPO 아니요. OS는 사용자에게 눈에 띄는 중단 없이 다양한 MPO 기능에 적응합니다.
PSR 두 GPU 모두 이 기능을 지원해야 합니다.
EDID/DisplayID 두 GPU 모두 동일한 EDID/DisplayId를 노출해야 합니다.
밝기 제한 두 GPU 모두 동일한 밝기 인터페이스와 밝기 캡을 지원해야 합니다.
밝기 수준 두 GPU 모두 동일한 밝기 수준 및 간격을 노출해야 합니다.
해상도 두 GPU 모두 동일한 소스 모드와 대상 해상도를 지원해야 합니다.
재생 빈도 자세한 내용은 GPU1에서 패널을 실행하는 GPU0의 새로 고침 속도를 지원하지 않는 경우 문제를 참조하세요.
동적 새로 고침 속도 아니요. OS는 다른 가상 새로 고침 속도 지원에 적응합니다.
가변 새로 고침 속도 자세한 내용은 GPU1에서 패널을 실행하는 GPU0의 새로 고침 속도를 지원하지 않는 경우 문제를 참조하세요.

GPU0가 패널에서 실행하는 새로 고침 속도를 GPU1이 지원하지 않을 경우 발생하는 문제

GPU1이 GPU0과 동일한 모드를 지원하지 않는 경우 축소된 모드는 표시 토폴로지 데이터베이스에 저장될 가능성이 높습니다. 그런 다음 시스템이 GPU0으로 다시 전환되면 축소된 모드가 설정됩니다. 예를 들어 GPU0에서 120Hz를 지원하지만 GPU1이 60Hz만 지원하는 경우 다음 시퀀스가 발생할 수 있습니다.

  1. GPU0가 디스플레이를 제어하고 모드가 120Hz가 되도록 시스템이 구성됩니다.
  2. 사용자가 수동으로 GPU1로 전환합니다.
  3. 디스플레이 토폴로지 데이터베이스에는 디스플레이에 대해 120Hz가 저장되어 있지만 GPU1은 이를 지원하지 않으므로 OS는 60Hz를 선택합니다.
  4. 60Hz는 표시 토폴로지 데이터베이스에 설정되고 저장됩니다.
  5. 사용자가 수동으로 GPU0으로 다시 전환합니다.
  6. 표시 토폴로지 데이터베이스는 데이터베이스에서 60Hz를 읽습니다.

최상의 환경을 제공하기 위해 OEM은 내부 패널의 최대 새로 고침 속도를 지원하는 iGPU 및 dGPU를 선택해야 합니다. 이것이 불가능하고 하나의 GPU가 패널의 최대 새로 고침 속도를 지원할 수 없는 경우 패널의 새로 고침 속도를 지원하는 GPU는 다음과 같은 범위가 포함된 Windows DRR(동적 새로 고침 속도) 기능을 지원해야 합니다.

  • 다른 GPU의 가장 높은 새로 고침 비율입니다.
  • 내부 패널의 가장 높은 새로 고침 비율입니다.

예를 들어 패널이 300Hz를 지원할 수 있고 iGPU가 60Hz만 지원할 수 있는 경우 dGPU는 60Hz~300Hz 이상의 범위의 VRR을 지원해야 합니다.

요약하자면 새로 고침 속도에 대한 ADS 요구 사항은 다음과 같습니다.

  1. iGPU 및 dGPU는 내부 패널의 최대 새로 고침 속도를 지원합니다.
  2. 내부 패널의 최대 새로 고침 속도를 지원하는 GPU는 다른 GPU가 지원할 수 있는 가장 높은 새로 고침 속도부터 내부 패널의 최대 새로 고침 속도까지 다양한 범위의 DRR을 지원해야 합니다.

HDR 및 Dolby Vision

OS는 전환 전 GPU0의 내부 패널에 설정되었던 것과 동일한 HDR/돌비 비전 상태를 전환 후 GPU1의 내부 패널에 설정합니다. 사용자는 변경 내용을 알 수 없습니다.

야간 조명

야간 조명은 WDDM 감마 또는 색 매트릭스 DDIS를 통해 구현됩니다. 두 경우 모두 OS는 스위치 전 GPU0과 마찬가지로 스위치 후 GPU1을 통해 동일한 야간 조명 수준을 설정합니다.

색상 프로파일

OS는 스위치 전에 적용된 것처럼 스위치 후 패널에 동일한 색 프로필을 적용합니다.

버그 확인 화면 표시

현재 OS는 비 POST 디바이스에서 버그 확인 화면 표시를 지원합니다. 버그 검사가 발생할 때 운영체제는:

  • mux를 전환하지 않습니다.
  • 현재 OS 지원을 사용하여 버그 확인 화면을 표시합니다.

잠재적인 타겟을 평가하여 버그 검사를 표시할 때, OS는 다른 타겟으로 전환되는 mux에 연결된 모든 타겟을 대상에서 제외합니다.

GPU0에서 멀리 떨어진 HPD가 처리되었지만 GPU1의 HPD가 아직 완전히 처리되지 않은 적은 기간이 있습니다. 이 기간 동안 버그 검사가 발생하면 사용자에게 버그 검사가 표시되지 않습니다. PSR이 여전히 활성화되어 있는 짧은 시간 동안 버그 검사가 발생할 경우, OS가 DxgkDdiSystemDisplayEnable를 호출할 때 디스플레이를 제어하는 드라이버는 패널이 PSR 모드에 있지 않도록 확인해야 합니다.

콘텐츠 적응 밝기 알고리즘

이상적인 환경에서는 두 GPU에서 사용하는 콘텐츠 적응 알고리즘이 동일한 효과를 생성해야 합니다. 그러나 동일한 효과가 나타나지 않을 가능성이 있으며, 내부 패널을 전환할 때 사용자가 차이를 느낄 수 있습니다.

밝기 데이터

사용자가 스위치로 인해 밝기 변경을 인지하지 못하도록 하려면 GPU0 및 GPU1에서 노출하는 모든 밝기 특성이 동일해야 합니다. 이 요구 사항은 GPU0에서 스위치가 이루어지기 전의 모든 밝기 수준이 스위치 후에 GPU1에서 지원됨을 보장합니다.

이렇게 하려면 GPU0 및 GPU1용 드라이버는 다음을 수행해야 합니다.

  1. 동일한 밝기 인터페이스, 즉 DXGK_BRIGHTNESS_INTERFACE_2 또는 DXGK_BRIGHTNESS_INTERFACE_3를 사용하며, 버전 3을 사용하는 것이 강력히 권장됩니다.
  2. 밝기 v3 인터페이스의 경우 두 드라이버 모두 nits 기반 또는 보정되지 않은 밝기를 제공해야 합니다.
  3. 밝기 v2 인터페이스의 경우, 두 드라이버 모두 GetPossibleBrightness명령을 통해 동일한 가능한 밝기 수준을 정확히 반환해야 합니다.
  4. 밝기 v3 인터페이스의 경우, 두 드라이버 모두 정확히 동일한 범위를 반환해야 합니다. 즉, 각 드라이버는 GetNitRanges에서 동일한 DXGK_BRIGHTNESS_GET_NIT_RANGES_OUT 구조를 반환해야 합니다.
  5. 드라이버가 OS 제공 밝기 수준을 패널별 설정으로 변환하는 데 사용하는 내부 테이블은 동일해야 합니다.

대부분의 노트북에서 GPU 드라이버는 비표준 방식으로 플랫폼에서 이 밝기 수준 데이터의 일부 또는 전부를 가져옵니다. 이러한 요구 사항을 달성하기 위해 이 플랫폼 간 GPU 데이터 교환을 확장해야 할 수 있습니다.

밝기 인터페이스는 어댑터 시작 시간에 쿼리되지만 내부 패널이 HPD'ed가 될 때까지 OS는 밝기 인터페이스의 DDI를 호출하지 않습니다. HPD는 mux가 GPU로 전환된 후 발생하므로 드라이버는 해당 시간에 내부 패널의 EDID에 액세스할 수 있습니다.

드라이버가 PWM을 지원하지 않는 패널의 패널 밝기를 설정하는 IHV 관련 방법이 있다는 것을 알고 있습니다. 그러나 이 메서드는 mux를 통해 연결된 GPU에 따라 다른 IHV별 방식으로 밝기를 가져오는 것을 지원해야 할 수 있으므로 TCon에 복잡성을 더합니다.

mux의 부팅 구성

시스템 펌웨어는 시스템 시작 시 내부 패널에 연결된 GPU를 제어합니다. OS는 패널을 마지막으로 제어한 GPU를 저장합니다. 그런 다음 부팅 시퀀스 중에 OS는 필요한 경우 mux를 전환하므로 올바른 GPU가 패널을 제어합니다.

mux 스위치가 필요할 때 부팅 이미지를 유지하기 위해 스위치는 다음 경우에만 수행됩니다.

  • 두 GPU 모두 전원이 켜집니다.
  • OS가 출력을 제어하는 부팅 그래픽에서 출력을 제어하는 DWM/셸로 전환되었습니다.

따라서 스위치는 DxgkddiSettimingsfromvidpn 내부 패널을 제어하는 GPU를 호출한 후 발생하며, 사용자는 스위치 중에 패널이 PSR에 있는 동안 고정된 화면을 경험하게 됩니다.

드라이버에 mux 정보 제공

이 기능은 드라이버가 언제든지 호출할 수 있는 콜백을 제공하는 대신 OS에서 드라이버를 호출하여 정보를 제공하도록 의도적으로 설계되었습니다. 이 메서드는 스위치 시퀀스 중에 OS 상태를 쿼리하는 경우 드라이버가 혼동되는 것을 방지합니다.

OS는 드라이버의 DxgkDdiDisplayMuxUpdateState DDI를 호출하여 다음과 같은 경우 드라이버에 현재 mux 상태를 제공합니다.

  1. 드라이버 시작 시 패널이 연결되지 않은 경우, 드라이버가 적시에 폴링 시퀀스를 방지할 수 있습니다.
  2. Dx에서 D0으로 돌아갑니다. 일부 전원 상태에서 복귀할 때(예: 최대 절전 모드), 펌웨어가 mux를 다시 설정해야 할 수 있습니다. 따라서 드라이버는 상태를 알 수 없습니다.

이러한 경우는 스위치 시퀀스에 관련된 일반 DDI와 함께 드라이버가 GPU가 활성 상태일 때마다 mux가 전환되는 방식을 결정할 수 있도록 합니다.

이 기능의 첫 번째 버전에서는 내부 패널이 활성화되지 않은 경우 mux를 전환할 계획이 없으므로 모든 스위치가 동일한 시퀀스를 통과합니다.

어댑터 시작 시간

드라이버가 시작되면 운영 체제의 폴링 요청에 응답해야 합니다. 드라이버는 멀티플렉서가 자신에게 전환되었는지 알아보기 위해 통신을 시도할 수 있지만, 이는 시간이 오래 걸리거나 신뢰할 수 없는 방법일 수 있습니다. GPU 시작 시퀀스의 일부로 OS는 mux에 연결된 각 대상에 대해 DxgkDdiDisplayMuxUpdateState DDI를 호출하고 해당 대상으로 전환되는지 여부를 나타냅니다.

드라이버가 시작되면 운영 체제의 폴링 요청에 응답해야 합니다. 드라이버는 OS와 통신하여 mux가 GPU로 전환되는지 여부를 검색하려고 시도할 수 있지만 시간이 오래 걸리거나 신뢰할 수 없을 수 있습니다.

대신, GPU 시작 시퀀스의 일부로 운영 체제(OS)는 mux에 연결된 각 대상에 대해 DxgkDdiDisplayMuxUpdateState를 호출하여 mux가 그 대상으로 전환되었는지 여부를 나타냅니다. OS는 폴링 DDIs를 호출하기 전에 mux가 드라이버의 GPU로 전환되었는지 여부를 드라이버에게 보고합니다.

ADS 드라이버는 OS가 DxgkDdiQueryAdapterInfo(DXGKQAITYPE_INTEGRATED_DISPLAY_DESCRIPTOR2)를 호출하여 내부 패널 세부 정보를 쿼리하는 것과 같은 방식으로 계속하여 내부 패널을 OS에 보고합니다. 드라이버는 DXGK_CHILD_CAPABILITIES.HpdAwareness가 mux에 연결된 모든 대상에 대해 HpdAwarenessInterruptible로 설정되도록 확인해야 합니다.

D0 전환

연결된 mux가 있는 GPU가 저전력 상태에서 전원이 켜진 상태로 반환될 때마다 OS는 DxgkDdiDisplayMuxUpdateState 호출하여 mux가 대상에 연결되어 있는지 또는 다른 GPU로 전환되었는지 여부를 드라이버에 알릴 수 있습니다.

부팅 시퀀스

다음 부팅 시퀀스는 ADS 관련 측면을 강조 표시합니다. 이 시퀀스에서 시스템은 다음을 사용하여 부팅합니다.

  • mux에 연결된 iGPU입니다.
  • 다시 부팅하기 전에 사용자의 마지막 구성은 mux가 dGPU에 연결되었다는 것입니다.

부팅 시퀀스는 기본적으로 비동기이므로 이 시퀀스는 예를 들어 용도로만 사용됩니다.

  1. 시스템 전원이 켜지고 iGPU가 mux를 통해 패널에 연결됩니다.
  2. iGPU는 패널에 부팅 화면을 표시합니다.
  3. Windows는 내부 뚜껑에 부팅 애니메이션을 로드하고 표시합니다.
  4. iGPU 및 dGPU 모두의 _DEP로 인해 OS의 mux 드라이버가 GPU 드라이버보다 먼저 시작됩니다. mux 드라이버는 ACPI 호출을 사용하여 mux가 올바르게 구성되었는지 확인합니다. mux 드라이버는 ACPI mux 구현이 ADS 요구 사항을 충족하는지 확인합니다.
  5. Dxgkrnl에서 iGPU에 대한 DxgkDdiAddDevice를 호출합니다.
  6. DxgkrnliGPU에 대해 DxgkDdiQueryInterface(DXGK_DISPLAYMUX_INTERFACE)를 호출합니다. 현재 시스템에서 ADS를 지원하지 않더라도 드라이버는 ADS를 지원하는 경우 해당 인터페이스를 반환합니다.
  7. Dxgkrnl은 드라이버의 ADS 지원 수준을 얻기 위해 DxgkDdiDisplayMuxGetDriverSupportLevel를 호출합니다.
  8. DxgkrnlDxgkDdiDisplayMuxReportPresence(TRUE)를 호출하여 시스템에 작동하는 ADS mux가 있음을 iGPU에 알릴 수 있습니다.
  9. DxgkrnlDxgkDdiStartDevice호출합니다. iGPU 드라이버는 내부 패널의 VidPn 대상을 포함하여 자식의 수를 반환합니다.
  10. DxgkrnlDxgkDdiDisplayMuxGetRuntimeStatus를 호출하여 iGPU가 ADS를 지원하는지 여부와 드라이버가 시스템에서 필요한 모든 정보를 얻었는지 여부를 확인하는.
  11. Dxgkrnl은 iGPU가 노출하는 각 자식에 대해 DxgkDdiQueryChildStatus를 호출합니다.
  12. Dxgkrnl이(가) mux에 연결된 iGPU에서 보고된 하위 장치를 찾으면 DxgkDdiDisplayMuxUpdateState을(를) 호출하여 mux가 해당 목표에 연결되어 있다고 iGPU에 알립니다.
  13. iGPU가 연결된 내부 모니터를 노출했기 때문에 DxgkrnlDxgkddiSettimingsfromvidpn을(를) 사용하여 iGPU에서 모드를 설정합니다.
  14. Dxgkrnl dGPU 드라이버를 시작한 다음 dGPU에 대해 5-12단계를 반복합니다.
  15. Dxgkrnl iGPU, dGPU 및 mux가 모두 올바르게 구성되어 있음을 감지하므로 mux 쌍과 mux 쌍에 대한 PnP 디바이스 인터페이스 속성을 만듭니다.
  16. Dxgkrnl 레지스트리에서 마지막 mux 구성을 읽습니다. 마지막 구성이 dGPU이기 때문에 Dxgkrnl 이제 mux를 dGPU로 전환하기 위해 이전에 설명한 mux 스위치 시퀀스를 시작합니다.

패널 드라이버

모니터 패널 드라이버는 EDID에서 생성된 PnP 하드웨어 ID를 기반으로 로드됩니다. EDID가 동일하게 유지되면 GPU가 내부 패널을 제어할 때 패널 드라이버가 로드됩니다. 두 드라이버 모두 동일한 밝기 기능을 제공합니다. 따라서 로드하면 문제가 발생하지 않으며 패널 드라이버는 mux를 제어하는 GPU를 알 필요가 없습니다.

mux로 제어하는 대상을 식별하기

OS가 드라이버를 시작하면 드라이버의 DxgkDdiQueryChildRelations 호출하여 보고된 자식에 대한 정보를 쿼리합니다. 드라이버는 각 자식에 대한 DXGK_CHILD_DESCRIPTOR 구조를 채웁니다. AcpiUid 멤버는 ACPI 네임스페이스의 해당 자식에 있는 _ADR 메서드에서 반환된 값으로 정의되며, 이를 통해 OS는 해당 자식의 ACPI 이름을 찾을 수 있습니다.

ADS의 경우 대상에 대한 자식 ACPI 네임스페이스 아래에 있어야 하는 ACPI DMID 메서드를 정의합니다. 이 DMID 메서드는 mux 디바이스의 ACPI 이름을 반환합니다. 이를 통해 OS는 대상에 대한 mux ACPI 이름을 찾을 수 있습니다.

PnP가 대상을 스캔 중인 어댑터를 중지하는 중

내부 패널로 스캔하는 GPU가 중지된 경우 OS는 mux를 전환하지 않습니다. 다음 시나리오는 GPU가 중지될 때 다양한 경우를 거꿉니다.

  1. GPU0는 게시물입니다. 내부 패널에 연결되어 중지됩니다.

    이 경우 BDD(기본 디스플레이 드라이버)는 GPU0에서 현재 활성 모드를 인수하고 화면을 계속 업데이트합니다.

  2. GPU0이 우선적인 위치에 있지만 GPU1은 내부 패널에 연결되어 있습니다. GPU0이 중지되었습니다.

    현재 OS 디자인으로 인해 BDD는 GPU0에서 시작되므로 고스트 모니터가 보고되고 디스플레이 CPL에 표시됩니다.

  3. GPU1은 게시물이 아니며 내부 패널에 연결됩니다. GPU1이 중지되었습니다.

    현재 OS 디자인으로 인해 BDD는 GPU1에서 시작되지 않으므로 사용자가 패널을 볼 수 없습니다.

  4. GPU1은 게시물이 아닙니다. GPU0이 내부 패널에 연결되고 GPU1이 중지됩니다.

    아무런 변화도, 아무 일도 일어나지 않습니다. GPU0는 패널에 계속 표시됩니다.

시나리오 2와 3은 사용자에게 나쁜 환경을 만듭니다. ADS 기능은 이러한 두 가지 경우를 해결하기 위해 동작을 변경합니다.

플러그 인/외부 GPU는 지원되지 않습니다.

플러그 인 GPU를 사용하는 이 기능에 대한 사용 사례는 없다고 생각합니다.

ADS는 단일 내부 패널로만 제한됩니다.

ADS의 첫 번째 버전은 단일 내부 패널만 지원합니다. 그러나 이 기능은 나중에 최소한의 드라이버 변경으로 외부 및 여러 내부 디스플레이(OS에서 지원되는 경우) muxing을 지원할 수 있는 방식으로 엔지니어링됩니다.

현재 POST 어댑터 정책 변경 내용

OS에는 이전에 POST 어댑터와 관련된 몇 가지 정책이 있었습니다. 예를 들어 POST 어댑터는 내부 대상을 노출할 수 있는 유일한 어댑터였습니다. 이러한 유형의 제한은 ADS가 도입되어 OS에서 제거됩니다.

모니터 도착 시각 효과 사용 안 함

Windows 11에서 모니터가 연결되면 셸/DWM에 애니메이션 시퀀스가 있습니다. 이 애니메이션은 디스플레이 스위치 시나리오에서 사용할 수 없습니다.

PnP bonk 사용 안 함

모니터를 추가하거나 제거하면 PnP 시스템에서 'bonk' 소리를 재생하여 사용자에게 알립니다. 이 'bonk' 기능은 디스플레이 전환 시나리오에서 비활성화됩니다.

애플리케이션 알림

디스플레이 스위치가 발생하면 시스템은 일반적인 HPD 제거 코드 경로와 HPD 도착 코드 경로를 거칩니다. 따라서 모든 일반 애플리케이션 알림은 정상적으로 트리거됩니다. 예를 들어, HPD 입력과 출력에 대한 PnP 알림 및 WM_DISPLAYCHANGE 창 메시지가 포함됩니다.

스위치를 트리거하는 API

OS 및 IHV 제어판이 스위치를 트리거할 수 있도록 공용 API를 사용하는 것이 계획입니다.

내부 패널이 단일 GPU에만 연결된 경우 디스플레이 API는 Win+P 기능과 함께 예상대로 작동합니다.

HLK 테스트

GPU 드라이버 또는 ACPI 펌웨어가 전체 ADS 지원을 보고하는 경우 ADS 지원 시스템에서 ADS HLK 테스트를 통과해야 합니다.

mux가 해당 GPU에서 멀리 전환될 때 GPU HPDing 내부 패널

OS는 'mux'가 현재 해당 드라이버에서 다른 것으로 전환되어 있을 때, 드라이버에서 내부 패널이 연결된 것으로 보고되면 버그 검사를 시작합니다.

AC/DC 전환

ADS 기능의 첫 번째 버전의 경우 OS는 AC 및 DC mux 설정을 저장하지 않으며 AC <> DC 전환에서 mux 스위치를 트리거하지 않습니다.

시스템 전원 전환

전원 전환 시의 주요 문제는 펌웨어가 mux 상태를 재설정할 때 (예: 최대 절전 모드) 전원이 다시 켜질 때 mux가 전환 이전의 패널로 돌아가지 않는 경우입니다.

초기 접근 방법은 iGPU와 dGPU를 모두 활성화한 후 mux를 dGPU로 다시 전환하는 것이었습니다. 이 방법의 문제는 서로 다른 비동기 이벤트에 따라 결과가 여러 모드 변경될 수 있다는 것입니다.

업데이트된 접근 방식은 사용자 환경을 간소화하기 위해 iGPU와 dGPU가 모두 절전 모드일 때 시스템이 mux를 예상 목표로 다시 전환하여 여러 모드 변경을 방지하는 것입니다.

전원 전환 시퀀스

다음 예제에서는 ADS 시스템에서 전원 관리의 일환으로 최대 절전 모드로 전환하는 것에 대해 설명합니다.

  1. 시스템은 dGPU에 연결된 mux로 구성되어 있습니다.
  2. 시스템이 최대 절전 모드로 전환됩니다.
  3. iGPU와 dGPU는 모두 D3 전원으로 전환됩니다.
  4. 시스템이 전원을 끕니다.
  5. 사용자가 시스템을 켭니다.
  6. 펌웨어는 내부 패널에서 mux를 iGPU와 iGPU 디스플레이 부팅 순서로 설정합니다.
  7. Dxgkrnl 마지막 mux 구성(이 경우 dGPU)을 읽고 ACPI(이 경우 iGPU)를 사용하여 현재 mux 위치와 비교합니다. Dxgkrnl ACPI를 호출하여 mux를 dGPU로 전환합니다.
  8. Dxgkrnl iGPU를 D0으로 전환한 다음 iGPU의DxgkDdiDisplayMuxUpdateState를 호출하여 드라이버에 mux가 연결되어 있지 않음을 알립니다.
  9. Dxgkrnl dGPU를 D0으로 전환한 후, dGPU의 DxgkDdiDisplayMuxUpdateState를 호출하여 드라이버에게 mux가 연결되었음을 알립니다.
  10. Dxgkrnl dGPU에서 모드를 설정합니다.

AIO(All-in-One 시스템)

ADS를 지원하려는 모든 AIO 시스템에는 내부 패널이 두 GPU의 내부 대상 유형으로 노출되어야 합니다.

Mux ACPI 디바이스

OEM은 ACPI 네임스페이스에 mux 디바이스를 추가하고 mux를 작동하는 데 필요한 메서드를 제공합니다.

mux 디바이스가 ACPI 트리의 어디에나 있을 수 있으므로 GPU 드라이버는 mux의 ACPI 메서드를 호출해서는 안 됩니다. 두 GPU의 가장 가까운 공통 조상 아래에서 mux를 찾는 것이 좋습니다.

현재 mux 디바이스는 두 개의 입력만 지원하며 향후 mux가 그 이상을 지원할 것으로 기대하지 않으므로 디자인에서 각 mux에 두 개의 입력과 단일 출력을 가정할 수 있습니다.

시스템이 실행되는 동안에는 mux 디바이스를 중지할 수 없습니다. 숨겨진 시스템 디바이스입니다.

Mux 디바이스 ACPI 메서드

ACPI 디바이스에 대한 드라이버 스택만 디바이스에서 ACPI 메서드를 평가하기 위해 호출할 수 있습니다. 따라서 mux 디바이스 메서드를 호출하여 mux를 전환하려면 OS에 mux 디바이스에 대해 로드된 드라이버가 있어야 합니다. 이러한 이유로 OS는 이제 모든 디스플레이 스위치 mux에 대한 드라이버로 디스플레이 mux 드라이버를 제공합니다.

mux 디바이스에는 다음 메서드가 필요합니다.

  • _HID 하드웨어 ID로 mux 디바이스를 식별합니다. ACPI 디스플레이 mux용 'MSFT0005'을 예약했습니다.
  • DMQU(디스플레이 Mux 쿼리)는 mux의 현재 상태를 반환합니다.
  • DMCF(디스플레이 Mux 구성)는 mux를 구성합니다.

메서드 _HID(하드웨어 ID)

인수:

없음

반환:

하드웨어 ID('MSFT0005')를 포함하는 ASCII 문자열입니다.

DMQU 메서드(Mux 쿼리 표시)

향후 릴리스에서는 쿼리에 추가 정보를 추가할 예정입니다. 나중에 추가 쿼리를 사용하도록 설정하려면 Arg0 사용하여 쿼리 유형을 표시합니다. DMQU 메서드가 쿼리 형식을 이해하지 못하는 경우 지원되지 않는 메서드로 실패해야 합니다.

인수:

Arg0: 쿼리 유형을 지정하는 정수입니다. 다음 표에서는 쿼리 형식 값과 해당 의미를 나열합니다.

쿼리 형식 값 의미
1 현재 스위치 상태 쿼리
2 mux ADS 지원 수준 쿼리
3 mux가 연결된 첫 번째 GPU 자식을 쿼리합니다.
4 mux가 연결된 두 번째 GPU 자식을 조회하기

반환:

메서드가 지정된 쿼리 형식을 이해하면 다음 표에 설명된 대로 적절한 데이터를 반환해야 합니다. 메서드가 지정된 쿼리 형식을 이해하지 못하는 경우 빈 문자열을 반환해야 합니다.

쿼리 형식 값 데이터 반환
1 mux가 현재 전환된 GPU 자식 디바이스의 ACPI 이름을 포함하는 ASCII 문자열입니다.
2 ADS 지원 수준을 나타내는 정수입니다. 자세한 내용은 다음 표를 참조하세요.
3 mux가 연결된 첫 번째 GPU 자식 디바이스의 ACPI 이름을 포함하는 ASCII 스팅입니다.
4 mux가 연결된 두 번째 GPU 자식 디바이스의 ACPI 이름을 포함하는 ASCII 문자열입니다.

다음 표에서는 쿼리 유형이 2일 때 ADS 지원 수준 값 및 해당 의미를 나열합니다.

반환된 데이터 의미
0 지원 없음
1 개발 지원. 시스템은 고객 시스템에서 기본적으로 ADS가 사용 중지된 상태로 출하되므로, HLK 테스트를 통과하지 않고도 이러한 설정을 사용할 수 있습니다.
2 실험적 지원. 시스템은 고객 시스템에서 기본적으로 ADS가 사용 중지된 상태로 출하되므로, HLK 테스트를 통과하지 않고도 이러한 설정을 사용할 수 있습니다.
3 전폭적인 지원. ADS는 지원되는 전체 그래픽 드라이버와 쌍을 이루는 경우 이 시스템에서 기본적으로 사용하도록 설정됩니다. 시스템은 선적되기 위해 ADS HLK 테스트를 통과해야 합니다.

DMCF 메서드(Display Mux Configure)

인수:

Arg0: mux가 전환해야 하는 ACPI GPU 자식 디바이스의 ASCII 이름입니다.

반환:

정수 0은 성공을 의미합니다. 0이 아닌 경우 실패를 나타냅니다. OEM은 더 나은 진단을 위해 0이 아닌 값을 정의할 수 있습니다.

GPU 디바이스 ACPI 메서드

GPU에 대한 그래픽 드라이버가 시작되기 전에 시스템은 mux ACPI 디바이스가 작동하는지, 그리고 현재 상태를 알고 있어야 합니다. 이렇게 하려면 ACPI mux 디바이스의 드라이버를 이미 시작해야 합니다. 시스템은 각 GPU의 ACPI 네임스페이스에서 ACPI _DEP 메서드를 사용하여 디바이스 관계를 보장합니다.

GPU에 이미 _DEP 메서드가 있는 경우 반환된 의존성 목록에 mux 디바이스의 ACPI 이름을 추가해야 합니다. GPU에 아직 _DEP 메서드가 없는 경우 해당 메서드를 추가해야 합니다.

OS가 ADS를 지원하는 경우에만 ACPI 펌웨어가 mux에 대한 GPU의 종속성을 선언하도록 하기 위해 ACPI _OSI 쿼리가 추가됩니다. ACPI 펌웨어는 이 쿼리를 사용하여 ADS 지원을 확인할 수 있습니다. ADS를 지원하는 OS 버전은 _OSI(“DisplayMux”) ACPI 명령에 true를 반환하여 지원을 보고합니다.

GPU 자식 디바이스 ACPI 메서드

mux에 연결된 각 대상에 대해 해당 자식의 ACPI 디바이스는 연결된 mux 디바이스의 ACPI 이름을 반환하는 ACPI 메서드를 노출합니다. 자세한 내용은 에서 mux가 제어하는 대상을 식별하는 방법을 참조하세요.

메소드 DMID(디스플레이 Mux 식별자)

인수:

없음

반환:

이 출력이 연결된 ACPI mux 디바이스의 ACPI 이름을 포함하는 ASCII 문자열

본보기

다음 예제에서는 두 개의 GPU(GPU0 및 GPU1)와 mux가 있는 시스템이 ACPI 프레임워크 내에서 설정 및 관리되는 방법을 보여 줍니다.

  • mux 디바이스의 ACPI 이름은 'SB.MUX1'입니다.

  • GPU0의 경우:

    • GPU0의 ACPI 이름은 'SB.PCI0.GFX0'입니다.
    • VidPn 대상 0x40f04를 노출하며, 이는 DXGK_CHILD_DESCRIPTOR가 보고하고 AcpiUid 값이 0x400임을 나타냅니다.
    • mux에 연결된 대상에 해당하는 ACPI 자식 디바이스 이름은 'SB.PCI0.GFX0.DD1F'입니다.
    • ACPI 메서드 '_ADR'는 'SB.PCI0.GFX0.DD1F' 아래에서 0x400을 반환합니다. 이 반환 값은 OS가 이 ACPI 디바이스가 VidPn 대상 0x40f04 대응한다는 것을 알고 있는 방법입니다.
    • 'SB.PCI0.GFX0.DD1F' 아래의 ACPI 메서드 DMID는 'SB.MUX1'을 반환합니다.
  • GPU1의 경우:

    • GPU1의 ACPI 이름은 'SB.PCI0.PEG0.PEGP'입니다.
    • VidPn 대상 0x1103은 DXGK_CHILD_DESCRIPTOR가 보고하는 것으로, AcpiUid 값이 0x100임을 노출합니다.
    • mux에 연결된 대상에 해당하는 ACPI 자식 디바이스 이름은 'SB.PCI0.PEG0.PEGP.EDP1'입니다.
    • ACPI 메서드 '_ADR'는 'SB.PCI0.PEG0.PEGP.EDP1' 아래에서 0x100을 반환합니다. 이 반환 값은 OS에서 이 ACPI 디바이스가 VidPn 대상 0x1103 해당하는지 알고 있는 방법입니다.
    • 'SB.PCI0.PEG0.PEGP.EDP1' 아래의 ACPI 메서드 DMID는 'SB.MUX1'을 반환합니다.
  • OS는 GPU0 대상 0x40f04와 GPU1 대상 0x1103이 ACPI 이름 'SB.MUX1'을 사용하여 동일한 멀티플렉서에 연결되어 있음을 알고 있습니다.

  • GPU1이 현재 패널에 연결된 경우 OS는 'SB.MUX1'에서 'SB.PCI0.GFX0.DD1F'를 전달하여 DMCF 메서드를 호출하고 mux를 GPU0으로 전환할 수 있습니다.

다음 ACPI 컴퓨터 언어 코드는 예제의 관련 부분에 대한 것입니다. 플랫폼 논리에 대한 의사 코드는 <>로 둘러싸여 있습니다.


DefinitionBlock
{
    Device (MUX1) // This is _SB_.MUX1
    {
        Name (_HID, "MSFT0007")  // _HID: Hardware ID

        Method (DMQU, 1, Serialized)  // DMQU: Display Mux Query
        {
            Switch (ToInteger(Arg0))
            {
                Case (1)
                {
                    If (<Mux is in error>)
                    {
                        Return ("")
                    }
                    If (<Mux switched to GPU0>)
                    {
                        Return ("_SB_.PCI0.GFX0.DD1F")
                    }
                    Else
                    {
                        Return ("_SB_.PCI0.PEG0.PEGP.EDP1")
                    }
                }
                Case (2) 
                {
                    Return (1)  // Mux only has developmental support
                }
                Case (3)
                {
                    If (<Mux is in error>)
                    {
                        Return ("")
                    }
                    Return ("_SB_.PCI0.GFX0.DD1F")
                }
                Case (4)
                {
                    If (<Mux is in error>)
                    {
                        Return ("")
                    }
                    Return ("_SB_.PCI0.PEG0.PEGP.EDP1")
                }

            }
            // Unknown type
            Return ("")
        }

        Method (DMCF, 1, Serialized)  // DMCF: Display Mux Configure
        {
            If (<Arg0 does not match either of the GPU children this mux is connected to>)
            {
                Return (1) // Failure, use 1 to indicate this particular failure
            }

            // Switch the mux

            If (<Mux switch was successful>)
            {
                Return (0) // Success
            }
            Else
            {
                Return (2) // Failure, use 2 to indicate this particular failure
            }
        }
    }

    Scope (_SB_.PCI0.GFX0) // ACPI Device for GPU0
    {
        Method (_DEP, 0, NotSerialized)  // _DEP: Dependency on Mux device
        {
            If (_OSI(“DisplayMux”))
            {
                Return (Package {"_SB_.MUX1"})
            }
            Else
            {
                Return (Package (0x00){})
            }
        }

        Device (DD1F) // SB.PCI0.GFX0.DD1F which is child of GPU that is connected to the Mux
        {
            Name (_ADR, 0x400)  // _ADR: Matches the AcpiUid driver reports for the target connected to mux
            Method (DMID, 0, NotSerialized)  // DMID: ACPI name of the mux this target is connected to
            {
                Return ("_SB_.MUX1")
            }
        }
    }

    Scope (_SB_.PCI0.PEG0.PEGP) // ACPI Device for GPU1
    {
        Method (_DEP, 0, NotSerialized)  // _DEP: Dependency on Mux device
        {
            If (_OSI(“DisplayMux”))
            {
                Return (Package {"_SB_.MUX1"})
            }
            Else
            {
                Return (Package (0x00){})
            }
        }

        Device (EDP1) // SB.PCI0.PEG0.PEGP.EDP1 which is child of GPU that is connected to the Mux
        {
            Name (_ADR, 0x100)  // _ADR: Matches the AcpiUid driver reports for the target connected to mux
            Method (DMID, 0, NotSerialized)  // DMID: ACPI name of the mux this target is connected to
            {
                Return ("_SB_.MUX1")
            }
        }
    }
}

API 변경 내용

ADS 기능은 다음과 같은 공용 API 기능을 추가합니다.

  1. 시스템의 mux 디바이스를 열거합니다.
  2. mux에 대한 정보 쿼리: 예를 들어, 어떤 대상에 연결되어 있고 현재는 어떤 대상으로 전환되어 있는지를 알아봅니다.
  3. mux 스위치를 트리거합니다.
  4. mux가 전환된 시기를 감지하는 방법입니다.

시스템의 멀티플렉서 장치를 나열하십시오.

애플리케이션은 일반적으로 사용 가능한 플러그 앤 플레이 API를 통해 작동하는 디스플레이 mux를 나타내는 장치 인터페이스를 찾을 수 있습니다. 사용자 모드 구성 요소는 Windows.Devices.Enumeration.DeviceInformation사용할 수 있습니다. 이러한 API와 함께 C# 또는 C++를 사용하여 mux 디바이스를 열거할 수 있습니다.

// Display Mux device interface
// {93c33929-3180-46d3-8aab-008c84ad1e6e}
DEFINE_GUID(GUID_DEVINTERFACE_DISPLAYMUX, 0x93c33929, 0x3180, 0x46d3, 0x8a, 0xab, 0x00, 0x8c, 0x84, 0xad, 0x1e, 0x6e);

IDisplayMuxDevice 인터페이스

mux 디바이스를 나타내기 위해 IDisplayMuxDevice 인터페이스가 추가됩니다.

다음 코드에서는 디스플레이 mux 디바이스를 열거하고, 상태를 쿼리하고, 활성 디스플레이 대상을 전환하고, Windows 런타임 API를 사용하여 상태 변경에 대응하는 방법을 보여 줍니다.

#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Devices.Enumeration.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Devices.Display.Core.h>

#include <string>
#include <sstream>
#include <iomanip>
#include <windows.h>

namespace winrt
{
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Foundation::Collections;
using namespace winrt::Windows::Devices::Enumeration;
using namespace winrt::Windows::Devices::Display;
using namespace winrt::Windows::Devices::Display::Core;
} // namespace winrt

void SwitchDisplayMuxTarget()
{
    // PnP device interface search string for Mux device interface
    std::wstring muxDeviceSelector = L"System.Devices.InterfaceClassGuid:=\"{93c33929-3180-46d3-8aab-008c84ad1e6e}\" AND System.Devices.InterfaceEnabled:=System.StructuredQueryType.Boolean#True";

    // Execute the device interface query
    winrt::DeviceInformationCollection deviceInformations = winrt::DeviceInformation::FindAllAsync(muxDeviceSelector, nullptr).get();
    if (deviceInformations.Size() == 0)
    {
        printf("No DisplayMux devices\n");
        return;
    }
    printf("%ld display mux devices found\n\n", deviceInformations.Size());

    // Only one mux in first release but here is generic code for multiple
    for (unsigned int i = 0; i < deviceInformations.Size(); i++)
    {
        printf("Display Mux device %ld :\n", i);

        // Get the device interface so we can query the info
        winrt::DeviceInformation deviceInfo = deviceInformations.GetAt(i);

        // Get the device id
        std::wstring deviceId = deviceInfo.Id().c_str();
        printf("    Device ID string : %S \n", deviceId.c_str());

        // Create the DisplayMuxDevice object
        auto displayMuxDevice = winrt::DisplayMuxDevice::FromIdAsync(deviceId).get();
        if (!displayMuxDevice)
        {
            printf("Failed to create DisplayMuxDevice object");
            continue;
        }

        // Check if DisplayMux is active
        auto displayMuxActive = displayMuxDevice.IsActive();
        printf("    DisplayMux state : %s \n", displayMuxActive ? "Active" : "Inactive");
        if (!displayMuxActive)
        {
            continue;
        }

        // Register for call back when the state of the DisplayMux changes
        UINT changeCount = 0;
        auto token = displayMuxDevice.Changed([&changeCount](auto, auto Args) -> HRESULT {
            changeCount++;
            return S_OK;
        });

        // Find targets connected to the DisplayMux and the current target
        auto targetsList = displayMuxDevice.GetAvailableMuxTargets();
        winrt::DisplayTarget currentTarget = displayMuxDevice.CurrentTarget();

        // Switch the display mux to the other target
        // NOTE SetPreferredTarget() is a sync method so use .get() to wait for the operation to complete
        printf("\n");
        if (currentTarget == targetsList.GetAt(0))
        {
            printf("DisplayMux currently connected to first target\n");
            displayMuxDevice.SetPreferredTarget(targetsList.GetAt(1)).get();
            printf("Calling SetPreferredTarget to switch DisplayMux to second target\n");
        }
        else if (currentTarget == targetsList.GetAt(1))
        {
            printf("DisplayMux currently connected to second target\n");
            displayMuxDevice.SetPreferredTarget(targetsList.GetAt(0)).get();
            printf("Calling SetPreferredTarget to switch DisplayMux to first target\n");
        }
        else
        {
            printf("Could not find current target in target list\n");
        }

        // Now read the current position
        currentTarget = displayMuxDevice.CurrentTarget();
        targetsList = displayMuxDevice.GetAvailableMuxTargets();
        if (currentTarget == targetsList.GetAt(0))
        {
            printf("DisplayMux is now currently connected to first target\n");
        }
        else if (currentTarget == targetsList.GetAt(1))
        {
            printf("DisplayMux is now currently connected to second target\n");
        }
        else
        {
            printf("Could not find current target in target list\n");
        }

        // Now unregister for change callback and display the
        displayMuxDevice.Changed(token);
        printf("DisplayMux state change callback was called %ld times\n\n", changeCount);
    }
}

자동 디스플레이 전환에 대한 WDDM DDI 변경 내용

이 섹션에서는 ADS를 지원하기 위해 WDDM DDI에 대한 추가 및 변경 내용을 설명합니다. 이러한 변경 내용은 Windows 11 버전 24H2 업데이트 2025.01D(WDDM 3.2)부터 사용할 수 있습니다.

KMD의 ADS 지원 인터페이스를 쿼리하는 작업

DXGK_DISPLAYMUX_INTERFACE_2 인터페이스 구조가 추가됩니다. ADS 버전 2를 지원하는 데 필요한 운영체제-드라이버 호출이 포함되어 있습니다. OS 는 드라이버 시작 시 드라이버가 지원하는 ADS 인터페이스를 쿼리하며, InterfaceType 는 GUID_WDDM_INTERFACE_DISPLAYMUX_2로 설정됩니다.

(DXGK_DISPLAYMUX_INTERFACE에는 ADS 기능의 버전 1을 지원하는 데 필요한 OS-드라이버 호출이 포함되어 있습니다. 이 버전은 ADS 프리릴리즈 시기에 사용되었습니다.)

ADS를 지원하는 KMD 함수

KMD는 ADS를 지원하기 위해 다음 함수를 구현합니다. Dxgkrnl KMD의 DxgkddiQueryInterface호출을 통해 KMD의 ADS 기능 인터페이스를 가져옵니다.

드라이버가 자동 운전 시스템 기능을 보고함

OS가 DxgkDdiDisplayMuxGetDriverSupportLevel DDI를 호출할 때, 드라이버는 ADS 지원 수준을 보고합니다. 드라이버가 DXGK_DISPLAYMUX_INTERFACE 인터페이스를 구현하지 않는 경우 OS는 지원 수준을 DXGK_DISPLAYMUX_SUUPORT_LEVEL_NONE 것으로 간주합니다.

드라이버는 실행 중인 시스템에 관계없이 ADS 지원 수준을 보고해야 합니다. 드라이버에서 보고하는 지원 수준은 드라이버를 기반으로 해야 합니다. 드라이버는 ADS 지원 수준을 보고할 때 다음 조건을 고려하지 않아야 합니다.

  1. 시스템 OEM입니다.
  2. 시스템의 다른 GPU입니다.
  3. ACPI mux 디바이스의 존재 여부입니다.
  4. GPU의 ACPI 노드 아래에 있는 ACPI 항목의 존재 여부입니다.

어댑터 시작 시점에서의 보고 대상 업데이트

어댑터가 시작되면 DxgkDdiQueryChildRelations DDI를 통해 모든 자식 디바이스를 보고합니다. 보고서에는 mux에 연결된 모든 내부 대상이 포함됩니다. 내부 대상에는 DXGK_CHILD_CAPABILITIES가 포함되며, Type.IntegratedDisplayChild.DescriptorLength의 필드가 포함됩니다.

어댑터가 시작될 때 mux를 다른 GPU로 전환하면 문제가 발생합니다. 이 경우 드라이버는 내부 패널과 통신하여 EDID/DisplayId 크기를 쿼리할 수 없습니다. 따라서, GUID_WDDM_INTERFACE_DISPLAYMUX_2 인터페이스를 노출하는 드라이버는, 만약 mux가 현재 드라이버의 GPU로 전환되지 않은 경우, 어댑터 시작 시 DXGK_CHILD_CAPABILITIES.Type.IntegratedDisplayChild.DescriptorLength을 0으로 설정해야 합니다. 그렇지 않으면 OS가 어댑터 시작에 실패합니다.

OS는 첫 번째 MUX 스위치 작업 시 내부 설명자의 크기에 관한 내부 정보를 업데이트합니다.

연결 변경 업데이트

앞에서 설명한 것처럼 자동 디스플레이 스위치 시퀀스 중에 내부 패널 상태를 보고하는 ADS별 방법이 있습니다. 연결 변경 패킷이 ADS 스위치 시퀀스의 일부임을 나타내기 위해 DisplayMuxConnectionChange 플래그를 DXGK_CONNECTION_MONITOR_CONNECT_FLAGS에 추가한다. DisplayMuxConnectionChange 설정되면 MonitorStatusConnected 또는 MonitorStatusDisconnected연결 상태 자동 디스플레이 스위치와 관련이 있음을 나타냅니다.

DisplayMuxConnectionChange ADS 스위치 중에만 사용해야 하며 다른 용도로 사용하면 안 됩니다. 다음 ADS 경우에 사용해야 합니다.

  • 드라이버가 DxgkDdiDisplayMuxPreSwitchAway을(를) 처리하는 동안.

    내부 패널이 연결된 경우, 드라이버는 연결 변경 목록에 DXGK_CONNECTION_CHANGE 패킷을 추가해야 하며, 이는 DXGK_CONNECTION_CHANGE.ConnectionStatusMonitorStatusDisconnected로 설정하고 DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange를 1로 설정합니다. 이러한 설정은 드라이버가 내부 패널의 제어를 해제했음을 OS에 나타냅니다.

  • 드라이버가 DxgkDdiDisplayMuxPostSwitchToPhase1를 처리하는 동안.

    • 드라이버는 먼저 내부 패널이 연결되어 있는지 확인해야 합니다.
    • 패널이 연결된 경우, 드라이버는 DXGK_CONNECTION_CHANGE 패킷을 연결 변경 목록에 추가해야 하며, 이때 DXGK_CONNECTION_CHANGE.ConnectionStatusMonitorStatusConnected로 설정해야 합니다. 또한, DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange는 1로 설정됩니다.
    • 패널이 연결되지 않은 경우, 드라이버는 연결 상태 변화를 나타내는 목록에 DXGK_CONNECTION_CHANGE 패킷을 추가해야 하며, DXGK_CONNECTION_CHANGE.ConnectionStatus 값을 MonitorStatusDisconnected로 설정하고, DXGK_CONNECTION_CHANGE.MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange 값을 1로 설정해야 합니다.
  • 드라이버가 DxgkDdiDisplayMuxSwitchCanceled을 처리하는 동안.

    • DxgkDdiDisplayMuxSwitchCanceled에서 드라이버가 추가한 모든 변경 패킷은 DXGK_CONNECTION_CHANGE. MonitorConnect.MonitorConnectFlags.DisplayMuxConnectionChange 1로 설정됩니다.
  • 전환 중에 대상 폴링 요청이 들어올 경우, DisplayMuxConnectionChangeDxgkDdiDisplayMuxPreSwitchAway, DxgkDdiDisplayMuxPostSwitchToPhase1, 또는 DxgkDdiDisplayMuxSwitchCanceled에서 추가된 연결 변경 패킷에 대해서만 설정해야 합니다.

DxgkDdiSystemDisplayEnable에 대한 업데이트된 지침

ADS 드라이버의 DxgkDdiSystemDisplayEnable(/windows-hardware/drivers/ddi/dispmprt/nc-dispmprt-dxgkddi_system_display_enable) DDI가 호출되면, 드라이버는 DxgkDdiSystemDisplayEnable DDI 호출 종료 시 PSR을 비활성화해야 합니다.

OEM 지침

ADS 기능의 몇 가지 측면은 OS가 플랫폼에서 제어하는 수준보다 낮습니다. OEM이 제대로 작동하는지 확인하는 것이 중요합니다. 다음 목록에는 OEM에서 고려해야 하는 몇 가지 주요 사항이 요약되어 있습니다.

  • 하이브리드 통합 드라이버와 하이브리드 불연속 드라이버 모두 ADS를 지원해야 합니다.
  • 플랫폼에 대해 선택한 mux는 ACPI를 통해 제어할 수 있습니다.
  • mux 디바이스와 GPU 자식 ACPI 디바이스의 내부 대상에 대한 _HID, DMQU 및 DMCF 메서드가 구현되었으며, DMID ACPI 메서드를 포함하고 있습니다.
  • 두 GPU의 ACPI 디바이스는 모두 mux ACPI 디바이스에 대한 의존을 나타내기 위해 _DEP를 포함해야 합니다.
  • 두 GPU가 제공하는 밝기 인터페이스, 기능 및 범위가 정확히 일치합니다.
  • 밝기 데이터 섹션에서 자세히 설명한 것처럼, 밝기 V3 인터페이스는 밝기 V2 인터페이스보다 더 권장됩니다.
  • 모니터 패널 드라이버가 사용될 때, 코드는 GPU에 독립적이어야 합니다. 즉, 두 GPU 중 어느 것이 패널을 제어하든 동일한 논리를 사용할 수 있어야 합니다.
  • 적어도 내부 mux의 경우 mux를 전환하는 행위는 HPD 이벤트를 생성해서는 안 됩니다.
  • OEM이 시스템에서 mux를 사용하지 않도록 설정하려는 경우 Arg0이 2로 설정된 상태에서 호출할 때 DMQU ACPI 메서드는 0을 반환해야 합니다.
  • mux는 드라이버가 저전력인 경우에도 GPU 간에 전환할 수 있어야 합니다. 이 경우 PSR은 사용되지 않습니다.
  • mux가 한 GPU에서 다른 GPU로 전환되면 밝기 결함 없이 패널의 밝기를 유지해야 합니다. 다음 방법을 포함하여 여러 가지 방법으로 수행할 수 있습니다. OEM은 시스템이 스위치의 밝기를 유지하도록 하는 역할을 담당합니다.
    • DisplayPort Aux Nits를 기반으로 하는 밝기 조절을 사용합니다.
    • PWM 재구성을 통해 밝기 문제를 피하려면 Tcon을 사용하세요.
  • 사전 전환 및 전환 후 링크 구성이 EDID에 의해 공개되고 iGPU 및 dGPU에서 모두 지원되는 경우, 사용된 패널 및 Tcon은 자체 새로 고침(eDP의 PSR1 모드) 상태를 유지할 수 있습니다. 여기에는 다음이 포함되지만 이에 국한되지는 않습니다.
    • 재생 빈도
    • 활성 크기
    • 사용된 eDP 레인 수 및 레인 대역폭
    • eDP DSC 설정
    • 사용된 eDP VSC SDP 버전
    • 비 스위치 시나리오에 사용되는 PSR 버전 및 기능