잡다

Texture compression

갈색바람 2021. 1. 12. 00:01

Application 을 구동하기 위해서 연산을 담당하는 CPU 외에 구동에 필요한 리소스를 저장하는 메모리인 RAM이 필요하다. 마찬가지로 GPU 또한 그래픽 연산을 위한 RAM을 가지고 있으며 이는 무한하지 않다.

게임 등에서 렌더링 퀄리티를 올리는 데 많은 요소가 있지만 그 중 눈에 확연히 띄는 것은 아마 texture일 것이다. 고해상도의 texture 를 사용할 수록 결과물의 선명도에서 큰 차이를 보일 것이다. 다만 언급했다싶이 RAM의 제한때문에 무한정 큰 texture 를 사용할 수 없고 render scene에서 샘플링되는 고해상도의 texture가 많다면 cache hit, memory bandwidth 등에서 성능 하락을 야기하며 심할 경우 RAM 부족으로 프로그램을 돌릴 수 없는 상황까지 이르게 될 것이다.

더불어, 모바일 디바이스의 경우 단순히 RAM 점유율 문제 뿐만 아니라 memory 병목은 배터리 효율 또한 일으킬 수 있다. 

따라서 texture data를 압축하여 보관/사용 하는 것은 꽤나 중요한 일이다. 압축에는 크게 손실/비손실(lossy/lossless) 그룹으로 나눌 수 있을 것이며, 대표적인 손실 압축포멧은 JPEG, 비손실 압축포멧은 PNG를 들 수 있을 것이다. 다만 이런 압축 포멧은 GPU상에서 사용될 수 없는데, PNG의 경우 압축을 해제하는 시간이 컨텐츠에 따라 가변적이며 JPEG는 압축 해제에 걸리는 시간이 크다. 또한 정해지지 않은 압축비율로 인하여 GPU에서는 해당 포멧을 바로 사용하지 못하고 결국 bitmap data로 upload 후 사용 가능하다.

Texture compression을 GPU에서 활용하기 위해서는 다음과 같은 제약사항이 있다.

  • 압축 알고리즘이 간단하고 해제 시 걸리는 시간이 짧아야 하며
  • 압축비가 일정해야 한다

이러한 요건을 만족하는 포멧은 BC (Block Compression), ETC/EAC (Ericsson Texture Compression), ASTC (Adaptable Scalable Texture Compression) 등이 있다.

이러한 포멧들은 모두 lossy compression이며, 이미지 품질저하에도 불구하고 큰 압축률 (BC1의 경우 RGBA 이미지를 작은 4x4 pixel block로 만들며, 하나의 block을 8byte로 압축한다. 즉 8:1 압축비를 가지며 RGBA 1024x1024 이미지의 경우 4MB -> 0.5MB로 압축 가능하다)에 대한 이점이 있어 널리 쓰이고 있다.

다양한 압축 포멧이 있는 이유 중 하나는 특허 문제로, BC1~5 의 압축포멧을 사용하기 위해서는 특허료를 내야했다. 이를 피하기 위해 모바일 GPU vendor에서 ETC1, ETC2 등을 개발하였고 Android 단말에서는 거의 표준으로 사용되고 있다. 또한 컨텐츠에 따라 각 압축 포멧 별로 좋은 품질을 유지하는 것이 달라 다양하게 쓰이고있다. ASTC는 그 중 가장 최신에 나온 포멧이며 사용료가 없어 많이 사용되기 시작하며, Vulkan Core API에서 지원되며, OpenGL ES 3.1에서도 지원되기 시작한다.

특히 ASTC의 경우 block scale을 다르게 설정할 수 있어, 컨텐츠별로 block size를 변화시킬 수 있으며, ASTC 4x4의 경우 ETC 보다 품질이 좋아 normal map 등에도 사용할 수 있다. 

Compression of normals.png, a normal map, with DXT vs ASTC (Using ASTC Texture Compression for Game Assets, Nvidia)

 

그 외에 GPU vendor사에서 사용하는 압축 알고리즘이 존재한다. 대표적인 예로 ARM의 AFBC (ARM Frame Buffer Compression)와 Qualcomm의 UBWC (Universial Bandwidth Compression)을 들 수 있다.

AFBC의 경우 Framebuffer 를 압축하는 것으로 lossless compression으로 품질에 영향을 주지 않으며, framebuffer에 있는 attachment가 AFBC 지원되는 포멧일 때 압축하여 load/store 에서 memory bandwidth 이점을 얻을 수 있다. 

Enabling AFBC in your Vulkan Application, ARM

위 그림과 같이 AFBC를 사용하였을 경우 tile 에 올라가 있던 attachment 정보를 store 하는 것을 알려주는 external write bandwidth 가 약 33% 줄어든 것을 알 수 있으며, 이는 memory bottleneck 상황에서 크게 성능을 향상함과 동시에 배터리 소모 또한 줄이는데 도움이 될 것이다.

UBWC 의 경우는 기존의 texture compression이나 AFBC와는 다르게, 이미지 버퍼에 한정되지 않고 지원되는 포멧이라면 모두 압축을하여 다른 IP에 전달하는 역할을 한다. 즉 texture 외에도 vertex/index buffer 등이 지원이 되는 포멧이라면 이를 모두 압축하여 전달하는 것이다. 

위와 같이 texture compression 을 사용할 경우 package size 뿐만 아니라 bandwidth 측면에서 큰 이득을 볼 수 있고 이는 성능 향상 또는 배터리 소모량을 줄여주게 된다. 또한 특정 GPU vendor에서 지원되는 compression 이 있는지 확인 하고 어떤 포멧이 지원되는지 확인하는 것이 좋다 (예로 attahcment의 포멧을 RGB8과 RGBA8 로 설정하고 비교하였을 때 RGB8을 위한 총 buffer size가 RGBA8 보다는 적을 것이지만, vendor compression에서 RGBA8만 지원된다면 실제 성능은 RGBA8가 더 좋게 나온다).

 

ref:

godotengine.org/article/betsy-gpu-texture-compressor

developer.nvidia.com/astc-texture-compression-for-game-assets

sv-journal.org/2014-1/06/en/index.php?lang=en

www.reedbeta.com/blog/understanding-bcn-texture-compression-formats/

arm-software.github.io/vulkan_best_practice_for_mobile_developers/samples/performance/afbc/afbc_tutorial.html

developer.qualcomm.com/qfile/34706/80-nb295-7_a-adreno_vulkan_developer_guide.pdf

'잡다' 카테고리의 다른 글

Bitonic sort  (0) 2020.12.22
OIT : Weighted, Blended OIT  (0) 2020.12.09
Order Independent Transparency  (0) 2020.12.03
Android Vulkan layer 적용  (0) 2020.11.18
Vulkan Layer  (0) 2020.11.14