거주
GPU에서 액세스할 수 있는 경우 개체는 상주 간주됩니다.
상주 예산
GPU는 아직 페이지 오류를 지원하지 않으므로 GPU가 액세스할 수 있는 동안 애플리케이션은 데이터를 실제 메모리에 커밋해야 합니다. 이 프로세스를 "상주하는 것"으로 알려져 있으며 물리적 시스템 메모리와 실제 불연속 비디오 메모리 모두에 대해 수행해야 합니다. D3D12에서 대부분의 API 개체는 GPU에 액세스할 수 있는 메모리의 양을 캡슐화합니다. 해당 GPU 액세스 가능 메모리는 API 개체를 만드는 동안 상주하게 되며 API 개체 소멸 시 제거됩니다.
프로세스에 사용할 수 있는 실제 메모리의 양을 비디오 메모리 예산이라고 합니다. 백그라운드 프로세스의 절전 모드 해제 및 절전 모드 해제로 예산이 눈에 띄게 변동할 수 있습니다. 사용자가 다른 애플리케이션으로 전환할 때 급격히 변동합니다. 예산이 변경되면 애플리케이션에 알림을 받고 현재 예산과 현재 사용된 메모리 양을 폴링할 수 있습니다. 애플리케이션이 예산 내에 유지되지 않으면 다른 애플리케이션을 실행할 수 있도록 프로세스가 간헐적으로 중지되거나 생성 API가 실패를 반환합니다. IDXGIAdapter3 인터페이스는 이 기능, 특히 QueryVideoMemoryInfoRegisterVideoMemoryBudgetChangeNotificationEvent관련된 메서드를 제공합니다.
애플리케이션은 예약을 사용하여 없이는 사용할 수 없는 메모리 양을 나타내는 것이 좋습니다. 이상적으로 사용자가 지정한 "낮은" 그래픽 설정 또는 더 낮은 값은 이러한 예약에 적합한 값입니다. 예약을 설정해도 애플리케이션은 일반적으로 받는 것보다 더 높은 예산을 제공하지 않습니다. 대신 예약 정보를 사용하면 OS 커널이 큰 메모리 압력 상황의 영향을 신속하게 최소화할 수 있습니다. 애플리케이션이 포그라운드 애플리케이션이 아닌 경우에도 애플리케이션에서 예약을 사용할 수 있도록 보장되지 않습니다.
힙 리소스
많은 API 개체가 일부 GPU 액세스 가능 메모리를 캡슐화하지만, 힙 & 리소스는 애플리케이션이 실제 메모리를 사용하고 관리하는 가장 중요한 방법이 될 것으로 예상됩니다. 힙은 실제 메모리를 관리하는 가장 낮은 수준 단위이므로 상주 속성에 익숙해지는 것이 좋습니다.
- 힙은 부분적으로 상주할 수 없지만 예약된 리소스를 사용하여 해결 방법이 존재합니다.
- 힙은 특정 풀의 일부로 예산을 책정해야 합니다. UMA 어댑터에는 하나의 풀이 있고, 불연속 어댑터에는 두 개의 풀이 있습니다. 커널이 불연속 어댑터의 일부 힙을 비디오 메모리에서 시스템 메모리로 이동할 수 있는 것은 사실이지만 극단적인 최후의 수단으로만 작동합니다. 애플리케이션은 커널의 예산 초과 동작에 의존해서는 안 되며, 대신 적절한 예산 관리에 집중해야 합니다.
- 힙은 상주에서 제거할 수 있으므로 해당 콘텐츠를 디스크로 페이징할 수 있습니다. 그러나 힙을 파괴하는 것은 모든 어댑터 아키텍처에서 상주를 확보하는 보다 안정적인 기술입니다. D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORTMaxGPUVirtualAddressBitsPerProcess 필드가 예산 크기에 가까운 어댑터에서 제거 안정적으로 거주를 회수하지 않습니다.
- 힙 만들기 속도가 느릴 수 있습니다. 그러나 백그라운드 스레드 처리에 최적화되어 있습니다. 렌더링 스레드의 결함이 발생하지 않도록 백그라운드 스레드에 힙을 만드는 것이 좋습니다. D3D12에서 여러 스레드는 create 루틴을 동시에 안전하게 호출할 수 있습니다.
D3D12는 애플리케이션에 더 많은 옵션을 사용할 수 있도록 리소스 모델에 더 많은 유연성과 직교를 도입합니다. D3D12에는 커밋, 배치 및 예약된 세 가지 고급 리소스 유형이 있습니다.
- 커밋된 리소스는 리소스와 힙을 동시에 만듭니다. 힙은 암시적이므로 직접 액세스할 수 없습니다. 힙의 크기가 적절하게 조정되어 힙 내에서 전체 리소스를 찾습니다.
- 배치된 리소스를 사용하면 힙 내의 0이 아닌 오프셋에 리소스를 배치할 수 있습니다. 오프셋은 일반적으로 64KB에 맞춰야 합니다. 그러나 일부 예외는 양방향으로 존재합니다. MSAA 리소스에는 4MB 오프셋 맞춤이 필요하며 4KB 오프셋 맞춤은 작은 질감에 사용할 수 있습니다. 배치된 리소스는 다른 힙으로 직접 재배치하거나 다시 매핑할 수 없습니다. 그러나 힙 간에 리소스 데이터를 간단하게 재배치할 수 있습니다. 다른 힙에 배치된 새 리소스를 만들고 리소스 데이터를 복사한 후에는 새 리소스 데이터 위치에 새 리소스 설명자를 사용해야 합니다.
- 예약된 리소스는 어댑터가 타일형 리소스 계층 1 이상에서 지원하는 경우에만 사용할 수 있습니다. 사용 가능한 경우 사용 가능한 가장 고급 상주 관리 기술을 제공합니다. 하지만 현재 모든 어댑터가 지원하는 것은 아닙니다. 리소스 설명자, 부분 밉 수준 상주 및 스파스 텍스처 시나리오 등을 다시 생성할 필요 없이 리소스를 다시 매핑할 수 있습니다. 예약된 리소스를 사용할 수 있는 경우에도 모든 리소스 유형이 지원되지 않으므로 완전히 일반적인 페이지 기반 상주 관리자는 아직 불가능합니다.
상주 우선 순위
Windows 10 크리에이터스 업데이트를 사용하면 개발자가 메모리 부족으로 인해 일부 리소스를 강등해야 하는 경우 어떤 힙과 리소스가 상주하는 것을 선호할지에 영향을 줄 수 있습니다. 이를 통해 개발자는 런타임이 API 사용에서 유추할 수 없다는 지식을 활용하여 더 나은 성능의 애플리케이션을 만들 수 있습니다. 개발자는 커밋된 리소스를 사용하여 재저질 및 타일식 리소스로 전환할 때 우선 순위를 지정하는 것이 더 편안하고 가능해질 것으로 예상했습니다.
이러한 우선 순위를 적용하는 것은 애플리케이션에서 이미 수행할 수 있으므로 리소스를 수동으로 강등 및 승격하는 두 개의 동적 메모리 예산을 관리하는 것보다 더 쉬워야 합니다. 따라서 상주 우선 순위 API의 디자인은 생성될 때 각 힙 또는 리소스에 할당된 합리적인 기본 우선 순위와 함께 기본적으로 세분화됩니다. 자세한 내용은 ID3D12Device1::SetResidencyPriority 및 D3D12_RESIDENCY_PRIORITY 열거형을 참조하세요.
우선 순위에 따라 개발자는 다음 중 하나를 수행해야 합니다.
- 이러한 힙이 자연 액세스 패턴에서 요구하는 것보다 더 빨리 또는 더 자주 강등되는 경험적 성능 영향을 더 잘 완화하기 위해 몇 가지 예외적인 힙의 우선 순위를 높입니다. 이 방법은 Direct3D 11 또는 OpenGL과 같은 그래픽 API에서 이식된 애플리케이션에서 활용될 것으로 예상되며, 리소스 관리 모델은 Direct3D 12와 크게 다릅니다.
- 프로그래머의 액세스 빈도에 대한 지식 또는 동적에 따라 고정된 애플리케이션 자체 버킷화 체계로 거의 모든 힙 우선 순위를 재정의합니다. 고정된 체계는 동적 구성표보다 관리가 더 간단하지만, 개발 과정에서 사용 패턴이 변경됨에 따라 덜 효과적이고 프로그래머 정품 인증이 필요할 수 있습니다. 이 접근 방식은 상주 라이브러리(특히 동적 체계)를 사용하는 것과 같이 Direct3D 12 스타일 리소스 관리를 염두에 두고 빌드된 애플리케이션에서 활용할 것으로 예상됩니다.
기본 우선 순위 알고리즘
애플리케이션은 먼저 기본 우선 순위 알고리즘을 밑줄로 설정하지 않고는 관리하려는 힙에 유용한 우선 순위를 지정할 수 없습니다. 힙에 특정 우선 순위를 할당하는 값은 동일한 메모리를 위해 경쟁하는 다른 우선 순위가 지정된 힙에 대한 상대적 우선 순위에서 파생되기 때문입니다.
기본 우선 순위를 생성하기 위해 선택한 전략은 힙을 두 개의 버킷으로 분류하는 것이며, 그렇지 않은 힙보다 GPU에서 자주 쓰는 것으로 간주되는 힙을 선호합니다(우선 순위가 더 높음).
우선 순위가 높은 버킷에는 렌더링 대상, 깊이 스텐실 버퍼 또는 UAV(순서가 지정되지 않은 액세스 뷰)로 식별하는 플래그로 만든 힙 및 리소스가 포함됩니다. 이 값은 D3D12_RESIDENCY_PRIORITY_HIGH; 범위에서 우선 순위 값이 할당됩니다. 이러한 힙 및 리소스 중에서 우선 순위를 더 지정하려면 우선 순위의 가장 낮은 16비트가 힙 또는 리소스의 크기로 10MB로 분할됩니다(매우 큰 힙의 경우 0xFFFF 포화). 이 추가 우선 순위 지정은 더 큰 힙 및 리소스를 선호합니다.
우선 순위가 낮은 버킷에는 D3D12_RESIDENCY_PRIORITY_NORMAL우선 순위 값이 할당된 다른 모든 힙 및 리소스가 포함됩니다. 이러한 힙 및 리소스 중 더 이상 우선 순위를 지정하지 않습니다.
프로그래밍 상주 관리
단순 애플리케이션은 메모리 부족 오류가 발생할 때까지 커밋된 리소스만 만들어 얻을 수 있습니다. 실패 시 애플리케이션은 커밋된 다른 리소스 또는 API 개체를 삭제하여 추가 리소스 생성이 성공할 수 있도록 할 수 있습니다. 그러나 간단한 애플리케이션조차도 부정적인 예산 변경을 감시하고 사용하지 않는 API 개체를 프레임에 대략 한 번 삭제하는 것이 좋습니다.
어댑터 아키텍처를 최적화하거나 상주 우선 순위를 통합하려고 할 때 상주 관리 디자인의 복잡성이 올라갑니다. 두 개의 불연속 메모리 풀을 별도로 예산 및 관리하는 것은 하나만 관리하는 것보다 더 복잡하며, 사용 패턴이 진화할 경우 광범위한 규모로 고정 우선 순위를 할당하면 유지 관리 부담이 될 수 있습니다. 시스템 메모리에 텍스처를 오버플로하면 시스템 메모리의 잘못된 리소스가 프레임 속도에 심각한 영향을 줄 수 있으므로 더 복잡해집니다. 또한 더 높은 GPU 대역폭을 활용하거나 낮은 GPU 대역폭을 허용할 리소스를 식별하는 데 도움이 되는 간단한 기능은 없습니다.
더욱 복잡한 디자인은 현재 어댑터의 기능을 쿼리합니다. 이 정보는 D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT, D3D12_FEATURE_DATA_ARCHITECTURE, D3D12_TILED_RESOURCES_TIER및 D3D12_RESOURCE_HEAP_TIER사용할 수 있습니다.
애플리케이션의 여러 부분이 다른 기술을 사용하여 발생할 수 있습니다. 예를 들어 일부 큰 텍스처와 거의 실행되지 않는 코드 경로는 커밋된 리소스를 사용할 수 있지만 많은 텍스처는 스트리밍 속성으로 지정되고 일반적인 배치 리소스 기술을 사용할 수 있습니다.
관련 항목