https://locketgoma.tistory.com/109
MetalFX For Unreal - 개발일지 5
MetalFX For Unreal - 개발일지 5 : 사실 MetalFX 업스케일러는 2개에요 부제가 모든걸 설명하는 이번 회고입니다. 사실 최근 작업의 하이라이트는 이번 회고에 포함된 0.3까지가 아니라 그 이후~오늘까지
locketgoma.tistory.com
지난 회고에 "다음 편도 곧 쓸듯" 이라고 적어놓고 거의 한달만에 다시 왔습니다 ㅋㅋㅋㅋ
그동안 좀 정신없는일들이 많았었네요. 쩝.
여튼, 기술적으로도 [개발일지 5] 기준인 0.31에서 이번 [개발일지 6] 기준인 0.4 까지 꽤 많은 변화가 있었습니다.
꽤 큰건
1. 샘플 프로젝트 외에 Lyra 등 "언리얼에서 제공해주는 정규 프로젝트" 에서도 테스트가 가능
2. 샤프닝 기능 추가
3. 실제로 성능 개선이 확인됨
이렇게였던거같네요.
그래서 무슨 일이 있었나요?
1. 하드코딩은 우선 줄이고 봅시다.
사실, 이전까지의 로직으로는 업스케일러 사용 여부 판단을 "하드코딩 된 값"으로 쓰고 있었습니다.
(간략하게) 알고 있던 정보로는, MetalFX 자체는 Metal3 이상, MetalFX Temporal Upscaler는 A17 이후 (Apple GPU 9) 에 사용 가능한것으로 알고 있어서, 이런 정보들을 하드코딩 해놨었어요.
그으으으치만... 이건 (그럴 일은 없어야겠지만) 지원 디바이스 정보가 바뀌면 그때그때 바꿔줘야 하는 문제점이 있습니다.
특히, MetalCpp / OS 레벨에서 정보가 바뀐다? 그때부터 버전관리 지옥이 시작되는 셈이죠.

해서, 업스케일러쪽에서 직접 지원해주는 supportsDevice 정보를 이용하기로 했습니다.
MTLFXTemporalScalerDescriptor::supportsDevice()
MTLFXSpatialScalerDescriptor::supportsDevice()
이렇게.
어차피 최종적으로는 Spatial Upscaler도 지원할거니까, 그걸 MetalFX 실행 기준으로, Temporal 은 별개의 검사로직으로 둔 것이죠.
또한, Temporal이 가능하다 -> Temporal만, Spatial만 가능하다 -> Spatial만 하는 방식으로, Primary Upscaler 충돌 문제를 방지하기 위한 보완 처리를 했습니다.
2. "Histroy" 는 1개가 아니다.
이건 뭔 소리인가 싶을거에요.
우선, Temporal Upscaler의 "Histroy" 개념에 대해 짧게 설명드리자면... 사실 이건 2개의 개념을 1개의 이름으로 묶어둔거에 가깝습니다.
Upscaler 에서 실제로 사용하는 History 는 "Temporal Upscaler에서 사용하는 기존까지의 업스케일러 결과물 기록" 이고, UE 환경에서 지원하는 History 는 "연속성 판단을 위한 토큰" 에 가까운 무언가인 셈이죠.

(어쩐지 DLSS History 클래스도 되게 간단하더니)
근데 이걸 2개가 아니라 1개로 생각하고 있으니, 이게 맞나? 하고 있던거지.
History 가 2개인걸 깨달은 이후, UE 환경에서의 History를 의미에 맞게 사용할 수 있게 개선을 했습니다. 역시나 DLSS 로직을 좀 참고했구요
오해를 막기위해 토큰 Histroy는 History(Token), 데이터 History는 History(Data) 로 적고 설명드리자면...
요약하자면, "이전 프레임과 연속되는지, 아닌지" 를 판별하는건데, 대체로 Histroy (Token) 를 유지하는 조건이
1. 카메라가 유지되는지 (카메라가 계속 같은 위치인지, 움직였는지 등등)
2. PrevHistroy가 존재하는지
인데, 둘중에 하나라도 만족하지 않으면 바로 Histroy (Token) 를 Reset으로 체크해서, History (Data)를 Reset 할지 말지를 결정하게 한것.
즉, 이제 진짜 "History" 를 활용하게 된 셈입니다.
3. Motion Vector 작업
역시나 DLSS 로직 도움을 받은 작업입니다. 고마워요 nvidia!
우선 Motion Vector 에 대해 간단히 설명드리자면, "직전 프레임 대비 픽셀이 어디로 옮겨젔는가" 를 보여주는 방향 벡터 텍스쳐... 로 이해하면 됩니다.
기존에는 제공되는 데이터를 그냥 들이박았는데, DLSS 로직을 좀 뒤져보니, 이걸 추가적인 쉐이더 처리를 통해 하더라구요?

그럼 해야지.
작업 스텝은 다음과 같이...
| UE Scene Velocity 존재 | UE Scene Velocity 없음 |
| DecodeVelocityFromTexture() | Depth + View.ClipToPrevClip |
| UE screen-space Velocity | Camera Motion 재구성 처리 |
| FrameBuffer Pixel-Space Motion Vector 변환 (for MetalFX) | |
| PF_G16R16F Velocity Texture 생성 | |
| MetalFX Temporal Upscaler 입력으로 사용 | |
진행되었고, 특히 "ScreenVelocity" 를 FrameBuffer Pixel 단위로 변환(디코딩) 하는 로직이 추가되었다는게 좀 큼.
풀어쓰자면, "기존의 UE Velocity Texture를 단순히 MetalFX 에 전달하는것에서 넘어, 별도 RDG Compute Pass에서 UE Velocity를 디코딩, Scene Velocity가 없는 Pixel의 경우 Depth 와 이전의 View Projection를 이용, Camera Motion을 복원한 후, 이 결과물들을 MetalFX에서 쓸 수 있게 pixel-Space Motion Vector로 변환해서 사용" 이라고... 할 수 있다.
(사실 어라 이게 이게 맞나 하는 느낌으로 써서 좀 헷깔리긴한데 그렇다고 합니다)
해서, 드디어 Motion Vector도 더미 데이터가 아닌 실질적인 데이터로 사용 가능!
4. 업스케일러에는 역시 샤프닝이지
꼭 업스케일러를 쓰진 않더라도, r.tonemapper.sharpen 이라는 명령으로 샤프닝을 임의로 쓸 수는 있다.
근데 이왕 MetalFX 쓰는거, 샤프닝도 MetalFX 에서 처리하면 좋지 않을까? 라는 개념으로 다른 모바일 업스케일러 (조금 구식인) 인 FSR1 로직을 참고했다.
만... 좀 어이없던 사실. 언리얼에서 기본 제공하던 모바일 FSR (FSR1)이 5.6.x 까진 있었는데, 5.7 으로 올라가면서 지원 목록에서 사라졌더라구요?
그래서 모바일 FSR 로직 찾는데 조금 걸리긴 했는데... 아무튼 그건 중요한거 아니고, 모바일 FSR에서 찾던건 바로 "RCAS" 로직
(Robust Contrast-Adaptive Sharpening 라고 부릅니다)
최종 출력 (정확히는 Primary Upcaler를 통해서 나온 최종 랜더링 결과물)에다 Sharpning을 추가해서, "선명한 테두리" 효과를 적용시켰습니다.
RCAS 로직이 보니까 좀 신기하던데, 진짜진짜 짧게 요약하면 흔히 쓰는 "현재 픽셀과 주변 픽셀의 대비를 강조" 하는 방식이더라구요.
여튼, 이렇게 RCAS 를 위한 "Secondary Upscaler" 슬롯을 사용, 배치하여 MetalFX 로 기동하는 Sharping 도 추가하였습니다. 짝짝.
5. 그리고 진짜 우연히 발견한 큰 이슈
...까지 작업하고, 테스트 중에 발견한 일이 하나 있었습니다.
기존 테스트는 그냥 사용하는 맥북에서 했는데, 맥북의 화면 출력을 외부 모니터에 연결해서 테스트하니까... 어라 뭔가 이상합니다?
출력되는 스케일이 확실하게 차이나는게 보이더라구요. 그래서 "이거 왜이러지?" 하고 좀 찾아보니까... 놀랍게도
GPU 단에서 만든 실제 Content Size가 Output Size와 다를 수 있다.
라는 사실이 나왔습니다.

즉...
MTLTexture Allocation Size != Input Contex Size != Output Size
라는 굉장한 사실.
이거에 대해서는, "Dynamic Input" 설정을 통해 작업하기로 했고, 사이즈 오차에 따른 대응을 마쳤습니다.
여기까지 하고나니까... 생각보다 분량이 크더라구요.
그리고, 이제는 "단순히 테스트 프로젝트말고 공식 샘플에다가도 넣어보자!" 해서 Lyra에 투입해보니, 성능 향상 약 10% 정도가 확인됐습니다.
https://github.com/LocketGoma/MetalFX/blob/main/Docs/PerformanceValidation.md
체감상, DLSS 3 정도의 성능인거같은데, 이정도만 해도 어디야 싶은 느낌.
일단 다음 작업은...... 취업하고 할거 같은데.......
노력해보겠습니다.

























