그래픽스 API가 필요 없는 시대를 향하여

1 month ago 11

  • 지난 10년간 DirectX 12, Vulkan, Metal 등 저수준 그래픽스 API는 GPU 성능을 끌어올렸지만, 복잡성과 유지비용이 급격히 증가함
  • 현대 GPU는 완전한 캐시 계층, 64비트 포인터, 바인드리스(bindless) 리소스를 지원해 기존의 복잡한 상태 객체와 바인딩 모델이 불필요해짐
  • 제안된 설계는 C/C++ 포인터 기반 메모리 접근단일 64비트 루트 포인터를 사용해 렌더링 파이프라인을 대폭 단순화
  • PSO 폭발, 리소스 배리어, 복잡한 바인딩 API를 제거하고, GPU 메모리와 셰이더 언어를 직접 연결하는 구조를 제시
  • 이 접근은 현대 GPU 아키텍처에 최적화된 차세대 API로, DirectX 13이나 Vulkan 2.0이 지향해야 할 방향을 제시함

저수준 그래픽스 API의 변화

  • 2013년 Xbox One과 PS4의 AMD GCN 아키텍처가 AAA 게임 개발의 표준이 되며, Mantle·DirectX 12·Vulkan·Metal 같은 저수준 API가 등장
    • 즉, 이들은 2013년 전후 GPU 아키텍처를 기준으로 설계됨
  • 기존 DirectX 11/OpenGL은 단일 스레드 렌더링과 높은 드라이버 오버헤드로 한계가 있었음
  • 이들 API는 사전 컴파일된 파이프라인 객체(PSO) 로 드로우콜 비용을 줄였지만, 엔진 구조와 맞지 않아 복잡성이 증가
  • 결과적으로 엔진 내부에 또 다른 “로우레벨 드라이버 계층”이 생겨, 그래픽스 프로그래머의 역할이 세분화됨

역사적 배경: 왜 이렇게 복잡해졌는가

  • 초기 GPU는 분리된 메모리와 고정 기능 파이프라인 중심 구조였음
  • OpenGL·DirectX는 하드웨어 다양성 추상화를 위해 상태 기반·객체 기반 설계를 채택
  • DirectX 11까지도 텍스처·버퍼가 불투명 디스크립터로 관리됨
  • 이러한 설계가 이후 API까지 관성처럼 유지

현대 GPU와 API의 불일치

  • 현재 GPU는 일관된 캐시 계층, PCIe ReBAR, 64비트 포인터, 바인드리스 텍스처를 지원
  • CPU가 GPU 메모리를 직접 쓰고 GPU가 즉시 읽는 구조 가능
  • 이러한 환경에서는 PSO·디스크립터 세트·바인딩 테이블 같은 구조가 불필요
  • PSO 캐시 폭증 문제로 인해 수백 GB의 캐시가 필요하며, 이는 로딩 지연과 스터터링의 원인
  • 새로운 API는 이러한 구시대적 구조를 제거하고 단순한 포인터 기반 접근으로 전환 가능

GPU 메모리 관리의 단순화

  • 기존 Vulkan/DirectX 12는 리소스 생성 후 힙 호환성 조회가 필요해 비효율적
  • 제안된 방식은 gpuMalloc/gpuFree 형태의 단순 API로 GPU 메모리를 직접 할당
    • CPU가 직접 GPU 메모리를 매핑해 초기화 가능
    • 대용량 데이터는 복사 명령으로 전송해 DCC 압축 및 swizzle 처리 수행
  • CPU 매핑 주소와 GPU 주소를 구분하며, gpuHostToDevicePointer로 변환

데이터와 셰이더 언어의 현대화

  • CUDA·Metal·OpenCL처럼 C/C++ 포인터 기반 셰이더 언어를 사용
  • 구조체 단위의 와이드 로드(128비트 이상) 로 효율적 메모리 접근 가능
  • DirectX의 ByteAddressBuffer텍셀 버퍼는 더 이상 최적이 아님
  • GLSL/HLSL은 포인터 미지원으로 재사용 가능한 셰이더 라이브러리 생태계 부재, 반면 CUDA는 풍부한 라이브러리로 발전

루트 인자와 데이터 구조

  • GPU 커널은 단일 64비트 포인터를 입력받아 구조체로 캐스팅
  • CPU와 GPU가 동일한 C/C++ 헤더를 공유해 데이터 구조 일관성 확보
  • const/restrict 키워드로 컴파일러 최적화 유도, 불필요한 UBO/SSBO 구분 제거
  • 현대 GPU의 스칼라 레지스터 프리로딩동적 유니폼 최적화를 활용

텍스처 바인딩의 단순화

  • 모든 텍스처를 256비트 디스크립터 배열(힙) 로 관리, CPU·GPU가 직접 쓰기 가능
  • 32비트 인덱스 기반 접근으로 비균일(non-uniform) 텍스처 샘플링 지원
  • DirectX 12 SM 6.6의 디스크립터 힙보다 단순하며, Vulkan VK_EXT_descriptor_buffer와 유사
  • 텍스처 객체 생성·업로드·샘플링이 모두 GPU 메모리 포인터 기반으로 통합

셰이더 파이프라인과 상수

  • 파이프라인 생성은 단순히 셰이더 IR 로드 후 gpuCreatePipeline 호출
  • 루트 시그니처, 디스크립터 세트, 바인딩 정의 불필요
  • 정적 상수(struct 기반) 로 셰이더 특수화 상수를 대체, PSO 조합 폭발 문제 완화
  • 상수 구조체에 GPU 포인터 포함 가능, 런타임 주소를 직접 하드코딩 가능

배리어와 동기화의 단순화

  • 기존 API의 리소스별 배리어 리스트는 현대 GPU 구조와 불일치
  • 제안된 모델은 큐/스테이지 단위 비트필드 플래그만 사용
  • gpuBarrier(before, after, hazard) 형태로 단순화, 리소스 추적 불필요
  • gpuSignalAfter / gpuWaitBefore 명령으로 타임라인 세마포어와 유사한 GPU→GPU 동기화 구현

커맨드 버퍼와 렌더링

  • 일회성(transient) 커맨드 버퍼만 사용, Vulkan의 복잡한 재사용 모델 제거
  • gpuBeginRenderPass / gpuEndRenderPass 로 렌더 타깃 설정 및 클리어 수행
  • 렌더패스 간 자동 배리어 없음, 병렬 렌더링 및 깊이 프리패스 최적화 가능

래스터 파이프라인 단순화

  • 버텍스/픽셀 셰이더는 포인터 기반 데이터 접근으로 바인딩 API 제거
  • GpuDepthStencilState, GpuBlendState를 PSO에서 분리해 조합 수 감소
  • 모바일 GPU는 프레임버퍼 fetch intrinsic으로 프로그래머블 블렌딩 지원
  • PSO는 최소한의 상태(토폴로지, 포맷, 샘플 수 등)만 포함

간접 드로우와 GPU 구동 렌더링

  • 모든 인자(data, arguments)를 GPU 포인터로 전달
  • gpuDrawIndexedInstancedIndirectMulti 로 멀티드로우 지원
  • GPU가 직접 루트 데이터와 드로우 인자를 생성 가능, 완전한 GPU-driven 렌더링 구현

툴링과 호환성

  • 포인터 기반 구조는 CUDA/Metal 디버거처럼 심볼 정보를 통해 추적 가능
  • 가상 메모리로 보호되어 보안 문제 없음, 잘못된 접근 시 페이지 폴트 발생
  • MoltenVK, Proton 사례처럼 기존 DirectX/Vulkan/Metal API를 변환 계층으로 호환 가능

최소 사양 및 결론

  • Nvidia Turing(2018) , AMD RDNA1(2019) , Intel Xe1(2022) , Apple M1(2020) 등은 모두 제안된 기능 지원
  • 요즘 GPU는 이미 바인드리스·64비트 포인터·일관 캐시 구조로 바뀌었음
  • API만이 과거의 추상화에 발목 잡혀 있음
  • 새로운 API는 DirectX 11보다 단순하고, Vulkan보다 빠르며, Metal보다 유연
  • 차세대 Vulkan 2.0 / DirectX 13은 이러한 완전 바인드리스 설계로 전환해야 하고, HLSL/GLSL 대신 C/C++ 포인터 기반 셰이더 언어로 생태계 확장을 추진해야 함

Read Entire Article