다음을 통해 공유


DXGI 프레젠테이션 경로

DXGI는 애플리케이션에 "그냥 작동"하는 프레젠테이션 방법론을 제공합니다. 예를 들어 애플리케이션은 창 모드와 전체 화면 모드 간에 전환하기 위해 특수 작업을 수행할 필요가 없습니다. DXGI와 사용자 모드 디스플레이 드라이버가 함께 작동하여 MSAA(다중 샘플 앤티앨리어싱), 모니터 회전, 후면 및 전면 버퍼의 크기 및 형식 차이, 전체 화면과 창 모드의 조합 간에 프레젠테이션을 유지하기 때문에 이 프레젠테이션 방법론이 가능합니다. DXGI의 또 다른 장점은 DXGI가 "상태 비저장" DDI를 제공하기 때문에 디스플레이 어댑터가 MSAA 및 회전된 표면을 스캔하는 기능이 제한적이라는 것입니다. 상태 비스테이션 DDI에서 어댑터의 드라이버는 DDI 호출에서 데이터를 기록할 필요가 없습니다.

프레젠테이션의 기본 작업은 렌더링된 백 버퍼에서 기본 화면으로 데이터를 이동하여 보는 것입니다. 이 작업은 다음 섹션에서 설명하는 다양한 상황에서 수행됩니다.

DWM이 켜진 창 모드

DWM(데스크톱 Windows 관리자)-on의 창 모드에서 DXGI는 DWM과 통신하고 DXGI 생산자의 렌더링 대상인 공유 리소스 보기와 DWM의 텍스처를 엽니다. 이 공유 리소스는 애플리케이션이 만드는 백 버퍼 외에 존재합니다. DXGI는 드라이버의 BltDXGI 함수를 호출하여 백 버퍼에서 공유 화면으로 데이터를 이동합니다. 이 작업에는 스트레치, 색 변환 및 MSAA resolve 필요할 수 있습니다. 그러나 이 작업에는 원본 및 대상 하위 사각형이 필요하지 않습니다. 실제로 BltDXGI 호출에서는 이러한 하위 사각형을 표현할 수 없습니다. 이 비트 블록 전송(비트블렛)은 항상 pBltData 매개 변수가 가리키는 DXGI_DDI_ARG_BLT 구조체의 Flags 멤버에 Present 플래그를 설정합니다. Present 플래그를 설정하면 드라이버가 원자성으로 작업을 수행해야 했음을 나타냅니다. 드라이버는 DWM이 컴퍼지션을 위해 공유 리소스를 읽는 동안 찢어질 가능성을 최소화하기 위해 비트blt 작업을 원자적으로 수행합니다.

DWM이 꺼진 창 모드

DWM 끄기를 사용하는 창 모드에서 DXGI는 pPresentData 매개 변수가 가리키는 DXGI_DDI_ARG_PRESENT 구조체의 Flags 멤버에 Blt 플래그가 설정된 드라이버의 PresentDXGI 함수를 호출합니다. 이 PresentDXGI 호출에서 DXGI는 DXGI_DDI_ARG_PRESENT hSurfaceToPresent 및 SrcSubResourceIndex 멤버에서 애플리케이션 에서 만든 백 버퍼를 지정할 수 있습니다. 추가 공유 표면이 없습니다.

전체 화면 모드

전체 화면 케이스는 DWM을 켜거나 끄는 창 모드보다 더 복잡합니다.

DXGI가 전체 화면 모드로 전환하면 대역폭을 줄이고 세로 동기화 동기화를 얻기 위해 대칭 이동 작업을 활용하려고 시도합니다. 다음 조건에서는 대칭 이동 작업을 사용하지 못할 수 있습니다.

  • 애플리케이션은 기본 표면과 일치하는 방식으로 백 버퍼를 다시 할당하지 않았습니다.

  • 드라이버가 백 버퍼를 검사하지 않도록 지정했습니다(예: 백 버퍼가 회전되거나 MSAA이므로).

  • 애플리케이션은 백 버퍼 내용의 Direct3D 런타임 삭제를 허용할 수 없음을 지정하고 체인에 하나의 버퍼(총)만 요청했습니다. 이 경우 DXGI는 백 서피스와 기본 표면을 할당합니다. 그러나 DXGI는 Blt 플래그가 설정된 드라이버의 PresentDXGI 함수를 사용합니다.

앞의 조건 중 하나가 발생하여 대칭 이동 작업을 방지하고 Blt 플래그 집합을 사용하여 드라이버의 PresentDXGI 함수를 호출하는 것도 적절하지 않은 경우(백 버퍼가 프런트 버퍼와 정확하게 일치하지 않기 때문에) DXGI는 프록시 표면을 할당합니다. 이 프록시 표면은 전면 버퍼와 일치합니다. 따라서 프록시 표면과 프런트 버퍼 간에 대칭 이동이 가능합니다. 프록시 표면이 있는 경우 DXGI는 드라이버의 BltDXGI 함수와 Present 플래그가 지워진(0)를 사용하여 애플리케이션의 백 버퍼를 프록시 화면에 복사합니다. 이 BltDXGI 호출에서 DXGI는 변환, 확장 및 해결을 요청할 수 있습니다. 그런 다음 DXGI는 DXGI_DDI_ARG_PRESENT 구조체의 Flags 멤버에 Flip 플래그가 설정된 드라이버의 PresentDXGI 함수를 호출하여 프록시 표면 비트를 스캔 아웃으로 이동합니다.

드라이버가 검색을 옵트아웃할 수 있음을 사용자 모드 표시 드라이버에 알리기 위해 드라이버는 선택적 및 선택적이 아닌 스캔 아웃 표면 클래스에 대한 리소스 생성 호출을 받습니다. 선택적 스캔 아웃 표면은 DXGI_DDI_PRIMARY_OPTIONAL 플래그로 지정됩니다. 선택 사항이 아닌 스캔 아웃 화면에는 DXGI_DDI_PRIMARY_OPTIONAL 플래그가 설정되어 있지 않습니다. 이러한 유형의 리소스 만들기 호출에 대한 자세한 내용은 리소스 생성 시 DXGI 정보 전달을 참조하세요.

DXGI는 DXGI_DDI_PRIMARY_OPTIONAL 플래그를 설정하여 모든 백 버퍼 표면(즉, 선택적 표면)을 만들고 전면 버퍼 또는 프록시 표면(즉, 선택적이 아닌 표면)에 대한 플래그를 설정하지 않습니다.

백 버퍼에 대해 DXGI_DDI_PRIMARY_OPTIONAL 설정된 경우 드라이버는 DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT 플래그를 설정할 수 있습니다. 이 플래그를 설정하는 방법에 대한 자세한 내용은 리소스 생성 시 DXGI 정보 전달을 참조하세요. 드라이버가 선택적 버퍼에 대한 DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT 설정하는 경우 DXGI가 Flip 플래그가 설정된 대신 Blt 플래그가 설정된 드라이버의 PresentDXGI 함수를 호출하도록 하는 것 외에는 아무런 효과가 없습니다.

프런트 버퍼 또는 프록시 화면에 대해 DXGI_DDI_PRIMARY_OPTIONAL 설정되지 않은 경우 드라이버는 오류 코드 DXGI_DDI_ERR_UNSUPPORTED 리소스 만들기 호출에 실패하고 DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT 설정하여 검색을 옵트아웃할 수 있습니다.

참고 DXGI_DDI_PRIMARY_DRIVER_FLAG_NO_SCANOUT 설정하지 않고 호출 만들기 실패는 메모리 부족과 같은 실제 오류 사례에 예약되어 있습니다.

DXGI는 MSAA 또는 회전된 버퍼에 대한 전체 화면 프레젠테이션 체인을 만들려고 할 때 이 옵트아웃 방법론을 활용합니다. 드라이버가 이러한 유형의 또는 둘 다를 검사하지 않으면 드라이버는 옵트아웃됩니다. 그런 다음 DXGI는 드라이버가 리소스 생성을 수락할 때까지 회전하지 않는 표면, 비 MSAA 표면 또는 둘 다를 만들려고 시도합니다. 따라서 선택 사항이 아닌 표면이 전면 버퍼 형식, 샘플 개수, 회전 및 크기와 정확히 일치할 때까지 DXGI는 점진적으로 대체됩니다.

드라이버가 선택 사항이 아닌 표면에서 옵트아웃하는 경우 DXGI는 여전히 백 버퍼에서 기본 표면으로 비트를 이동할 수 있는 방법이 있어야 합니다. 따라서 드라이버가 MSAA 및 회전에 대한 검색을 옵트아웃하는 경우 DXGI가 드라이버의 BltDXGI 함수를 호출할 때 드라이버가 확인, 회전 또는 둘 다에 옵트인합니다. 드라이버가 옵트아웃하면 DXGI는 프록시 표면을 만들고 BltDXGI 를 호출하여 백 버퍼에서 해당 프록시 화면으로 데이터를 이동합니다. 프록시가 프런트 버퍼와 정확히 일치하기 때문에 드라이버는 이 프록시 표면을 옵트아웃할 이유가 없어야 합니다.

애플리케이션이 전체 화면 모드로 전환하거나 전체 화면 모드에서 전환한 후 표면을 다시 만들지 않는 경우 다음과 같은 비정상적인 상황이 발생합니다.

  • 애플리케이션이 전체 화면 모드로 전환할 때 표면을 다시 만들지 않는 경우 DXGI는 백 버퍼가 실제로 형식, 크기, 회전 및 샘플 수와 일치하더라도 전면 버퍼와 일치하지 않는다고 결정합니다. 이러한 결정의 이유는 해당 버퍼를 만들 때 운영 체제에서 특정 모니터에 대한 검색을 위해 백 버퍼에 태그를 지정해야 하기 때문입니다. 전체 화면이 입력될 때 모니터가 동적으로 선택되기 때문에 창 뒤로 버퍼를 특정 모니터에 확실하게 할당할 수 없습니다. 따라서 DXGI는 검색을 위해(대칭 이동 작업을 통해) 드라이버에 이러한 백 버퍼를 보내지 않아야 합니다. 이 유형의 애플리케이션은 일반적으로 DXGI가 프록시 표면을 만들도록 강제합니다.

  • 애플리케이션이 창 모드로 돌아갈 때 백 버퍼를 다시 만들지 않는 경우 DXGI는 드라이버의 BltDXGI 또는 PresentDXGI ( Blt 집합 포함)를 호출하여 이전에 대칭 이동 작업을 위해 만든 표면에서 비트블렛을 수행할 수 있습니다. 이 상황은 문제가 되어서는 안 되지만 완전성을 위해 여기에 언급되어 있습니다. DXGI는 애플리케이션이 창 모드로 전환될 때 항상 프록시 표면을 삭제합니다.

또한 애플리케이션이 전체 화면 모드에 있는 동안 애플리케이션은 백 버퍼의 크기를 동적으로 조정할 수 있습니다. 이 작업을 수행하면 이전 상황에서 설명된 논리가 다시 발생합니다. 따라서 프록시 표면이 만들어지고 제거될 수 있으며, 애플리케이션이 전체 화면 모드로 유지되더라도 시간이 지남에 따라 옵트아웃이 필요할 수도 있고 필요하지 않을 수도 있습니다. 또한 애플리케이션은 전체 화면 모드를 벗어나지 않고 동적으로 출력을 다른 모니터로 전송할 수 있습니다. 따라서 애플리케이션의 백 버퍼가 다른 모니터에 대해 태그가 지정되었기 때문에 애플리케이션은 비트블렛 모드로 다시 전환됩니다.

마지막으로 드라이버가 MSAA 스캔 아웃을 옵트아웃하지 않는 경우 MSAA 백 버퍼와 관련하여 발생하는 상황을 알고 있어야 합니다. 이 경우 드라이버는 MSAA의 검색을 옵트아웃합니다. 따라서 DXGI는 대칭 이동 작업을 통해 MSAA 백 버퍼와 MSAA 프런트 버퍼를 교환하고 DAC(디지털-아날로그 변환기)와 동일한 resolve 작업을 수행합니다. 이 경우 애플리케이션은 전체 화면 모드에서 역 버퍼의 크기를 동적으로 조정할 수 있으므로 DXGI가 드라이버의 BltDXGI 함수 호출로 전환됩니다. 백 버퍼 및 프런트 버퍼의 MSAA 특성은 여전히 일치하므로 DXGI는 드라이버가 확인되지 않는 색 변환, 스트레치 비트blt를 수행하게 지정합니다. 그런 다음 드라이버는 resolve 없이 다중 샘플링을 전면 버퍼에 복제해야 하며, 이는 드라이버가 MSAA를 검사하도록 선택하는 경우에 필요합니다.