UMA 최적화: CPU 액세스 가능 텍스처 및 표준 혼합

UMA(Universal Memory Architecture) GPU는 특히 모바일 디바이스용으로 최적화할 때 개별 GPU에 비해 효율성이 약간 더 높습니다. GPU가 UMA일 때 리소스에 CPU 액세스 권한을 부여하면 CPU와 GPU 사이에 발생하는 복사의 양을 줄일 수 있습니다. UMA 설계에서 애플리케이션이 모든 리소스에 대한 CPU 액세스를 무조건 제공하는 것은 좋지 않지만, 적합한 리소스에 CPU 액세스를 제공하면 효율성을 개선할 수 있습니다. 개별 GPU와 달리, CPU에는 GPU가 액세스할 수 있는 모든 리소스에 대한 포인터가 기술적으로 포함될 수 있습니다.

CPU 액세스 가능 텍스처의 개요

그래픽 파이프라인에서 CPU 액세스 가능 텍스처는 UMA 아키텍처의 기능으로, CPU에서 텍스처에 대해 읽기 및 쓰기 액세스를 수행할 수 있도록 합니다. 더 일반적인 불연속 GPU에서는 CPU가 그래픽 파이프라인의 텍스처에 액세스할 수 없습니다.

텍스처에 대해 권장되는 일반적인 모범 사례는 개별 GPU를 수용하는 것입니다. 이를 위해 버퍼를 통해 텍스처 데이터 업로드에 제공되는 다음과 같은 프로세스를 수행합니다.

  • 대부분의 텍스처에 대해 CPU 액세스 권한이 없음
  • 텍스처 레이아웃을 D3D12_TEXTURE_LAYOUT_UNKNOWN.
  • CopyTextureRegion을 사용하여 GPU에 텍스처 업로드

그러나 특정 경우에 CPU와 GPU는 같은 데이터에 대해 자주 상호 작용할 수 있으므로 텍스처를 매핑하면 전력을 절약하거나 특정 어댑터 또는 아키텍처의 특정 디자인을 가속화하는 데 유용합니다. 애플리케이션은 이러한 경우를 감지하고 불필요한 복사를 최적화해야 합니다. 이 경우 최상의 성능을 위해 다음 사항을 고려하세요.

  • D3D12_FEATURE_DATA_ARCHITECTURE::UMA가 TRUE인 경우에만 텍스처 매핑의 더 나은 성능을 활용하기 시작합니다. 그런 후 힙에서 선택할 CPU 캐시 속성을 결정하는 경우 CacheCoherentUMA에 주의해야 합니다.

  • 텍스처에 대한 CPU 액세스를 활용하는 것이 버퍼의 경우보다 더 복잡합니다. GPU에 가장 효율적인 텍스처 레이아웃은 거의 row_major 않습니다. 실제로 일부 GPU는 텍스처 데이터를 복사할 때만 row_major 텍스처를 지원할 수 있습니다.

  • UMA GPU는 보편적으로 간단한 최적화를 활용하여 수준 로드 시간을 줄여야 합니다. UMA를 인지한 후에, 애플리케이션은 초기 CopyTextureRegion을 최적화하여 GPU가 수정하지 않을 텍스처를 채웁니다. 애플리케이션은 D3D12_HEAP_TYPE_DEFAULT 사용하여 힙에서 텍스처를 만들고 텍스처 데이터를 마샬링하는 대신 WriteToSubresource 를 사용하여 실제 텍스처 레이아웃을 이해하지 못하게 할 수 있습니다.

  • D3D12에서는 CPU 액세스가 없는 D3D12_TEXTURE_LAYOUT_UNKNOWN 사용하여 만든 텍스처가 잦은 GPU 렌더링 및 샘플링에 가장 효율적입니다. 성능 테스트 시 이러한 텍스처를 CPU 액세스가 있는 D3D12_TEXTURE_LAYOUT_UNKNOWN 비교하고 CPU 액세스로 D3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLE 어댑터 간 지원을 위한 D3D12_TEXTURE_LAYOUT_ROW_MAJOR 비교해야 합니다.

  • CPU 액세스와 함께 D3D12_TEXTURE_LAYOUT_UNKNOWN 사용하면 WriteToSubresource, ReadFromSubresource, Map (포인터에 대한 애플리케이션 액세스 제외) 및 매핑 해제 메서드를 사용할 수 있습니다. 하지만 GPU 액세스의 효율성을 희생할 수 있습니다.

  • CPU 액세스에 D3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLE 사용하면 WriteToSubresource, ReadFromSubresource, Map (애플리케이션에 대한 유효한 포인터를 반환함) 및 매핑 해제를 사용할 수 있습니다. CPU 액세스로 D3D12_TEXTURE_LAYOUT_UNKNOWN 이상의 GPU 액세스 효율성을 희생할 수도 있습니다.

표준 혼합 개요

D3D12(및 D3D11.3)는 표준 다차원 데이터 레이아웃을 도입했습니다. 이 기능은 여러 레이아웃 간에 데이터를 복사하거나 데이터를 혼합할 필요 없이, 여러 처리 단위가 동일한 데이터에 작동할 수 있도록 하기 위한 것입니다. 표준화된 레이아웃을 사용하면 네트워크 효과를 통해 효율성이 높아지며, 특정 패턴을 빠르게 가정하는 알고리즘이 허용됩니다.

텍스처 레이아웃에 대한 자세한 설명은 D3D12_TEXTURE_LAYOUT 참조하세요.

이 표준 혼합은 하드웨어 기능이지만 모든 GPU에서 지원하지 않을 수도 있습니다.

혼합에 대한 배경 정보를 보려면 Z-순서 곡선을 참조하세요.

API

D3D11.3과 달리 D3D12는 기본적으로 텍스처 매핑을 지원하므로 D3D12_FEATURE_DATA_D3D12_OPTIONS 쿼리할 필요가 없습니다. 그러나 D3D12가 항상 표준 스위즐을 지원하는 것은 아닙니다. 이 기능은 CheckFeatureSupport 를 호출하고 StandardSwizzle64KBSupported필드의 D3D12_FEATURE_DATA_D3D12_OPTIONS 확인하여 쿼리해야 합니다.

다음 API는 텍스처 매핑을 참조합니다.

열거형

  • D3D12_TEXTURE_LAYOUT : 기본 텍스처의 스위즐 패턴을 제어하고 CPU 액세스 가능한 텍스처에서 맵 지원을 사용하도록 설정합니다.

구조체

  • D3D12_RESOURCE_DESC : 텍스처와 같은 리소스를 설명합니다. 이는 광범위하게 사용되는 구조체입니다.
  • D3D12_HEAP_DESC : 힙을 설명합니다.

메서드

리소스 및 부모 힙에는 다음과 같은 맞춤 요구 사항이 적용됩니다.

  • 다중 샘플 텍스처에 대한 D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT(4MB)
  • 단일 샘플 텍스처 및 버퍼에 대한 D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT(64KB)입니다.
  • 선형 하위 리소스 복사는 D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT(512바이트)에 맞춰야 하며 행 피치는 D3D12_TEXTURE_DATA_PITCH_ALIGNMENT(256바이트)에 맞춰야 합니다.
  • 상수 버퍼 뷰는 D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT(256바이트)에 맞춰야 합니다.

64KB보다 작은 텍스처는 CreateCommittedResource를 통해 처리해야 합니다.

동적 텍스처(모든 프레임을 변경하는 텍스처)를 사용할 경우 CPU는 업로드 힙에 선형으로 쓰며, 그 다음에 GPU 복사 작업이 수행됩니다.

일반적으로 동적 리소스를 만들려면 업로드 힙에 대형 버퍼를 만듭니다(버퍼 내 하위 할당 참조). 준비 리소스를 만들려면 다시 읽기 힙에 대형 버퍼를 만듭니다. 기본 정적 리소스를 만들려면 기본 힙에 인접한 리소스를 만듭니다. 기본 별칭 리소스를 만들려면 기본 힙에 중복 리소스를 만듭니다.

WriteToSubresourceReadFromSubresource는 행 중심 레이아웃과 정의되지 않은 리소스 레이아웃 간에 텍스처 데이터를 다시 정렬합니다. 작업은 동기식이므로 애플리케이션은 CPU 일정을 고려해야 합니다. 애플리케이션은 항상 복사를 좀 더 작은 지역으로 분할하거나 다른 태스크에서 이 작업을 예약할 수 있습니다. 리소스 레이아웃이 불투명한 MSAA 리소스 및 깊이 스텐실 리소스는 이러한 CPU 복사 작업에서 지원되지 않으며 오류를 유발합니다. 요소 크기가 2의 거듭제곱이 아닌 형식도 지원되지 않으며 오류를 유발합니다. 메모리 부족 반환 코드가 발생할 수 있습니다.

핵심 상수

ID3D12Heap

리소스 바인딩