주의 : 초심자 튜토리얼은 아닙니다. 그러므로, 실제 API 호출 용례를 알고자 한다면, 샘플이나 튜토리얼을 찾아서 확인해 보세요.

주의 : 완전히 이해하고 작성한 글이 아니므로 잘못된 내용이 포함되어 있을 수 있습니다.

주의 : 이상하면 참고자료를 확인하세요.



일단 LunarG 나 Khronos group 의 문서들을 보면 셰이더 언어로 GLSL 을 리플렉션 라이브러리로 spirv-cross 를 소개하는 경우가 많습니다. 


그런데 HLSL 을 SPIR-V 로 변환하는 것과 관련해 설명하는 문서들에서는 리플렉션을 위해 spirv-reflect 를 소개하는 경우가 많습니다. 보통 이런 문서는 구글의 "Lei Zhang" 이라는 사람이 주로 발표하는데요, 이 분이 dxc 와 spirv-relfect 구현에 참여를 한 것으로 보입니다. 이 분은 github 에서 "antiagainst" 라는 계정을 사용하고 있습니다. 구글에서는 dxc 를 통해서 spirv-reflect 를 사용하도록 권장하는 모양인 것 같습니다. MS 도 아니고 구글이 그런 작업을 한다는 사실이 참 아이러니합니다.


spirv-reflect 는 매우 가볍습니다. 헤더 하나에 소스 하나입니다. [ SPIRV-Reflect ] 에 올라와 있으니 자유롭게 받으실 수 있습니다.


사용방법은 매우 간단한데요, 위의 링크를 참고하시면 쉽게 따라할 수 있습니다. 


단지 문제가 하나 있다면 해당 페이지의 코드 조각 중에서 input_vars 가 SpvReflectInterfaceVariable* 타입이 아니라 SpvReflectInterfaceVariable** 타입이어야 한다는 것입니다. 무작정 따라 하시면 나중에 크래시납니다. 게다가 input_vars 에 대한 메모리 해제도 안 하고 있으니 주의하셔야 합니다.


예제는 spvReflectEnumerateInputVariables() 함수만 소개하고 있는데요, 여러 종류의 열거 함수들이 있습니다. 자신의 필요에 맞게 함수를 호출해서 사용하면 됩니다.



위의 함수와 동일한 기능을 하는 ShaderModule 클래스의 래퍼 메서드들도 존재합니다. 어떤 스타일을 선호하느냐는 사용자가 결정하면 됩니다.



그런데 이건 좀 사용하기에 불편한 점이 있습니다. 예를 들면 아래와 같은 HLSL 코드를 살펴 봅시다.



여기에 대해 spvReflectEnumerateInputVariables() 를 호출하면 main() 함수의 인자인 PSInput 의 내용을 출력해 줍니다. 하지만 이름이 맹글링되어 있고 제대로 유지되지 않는 것을 알 수 있습니다.  Color, Alpha, Scaling 등의 정보가 시맨틱과 비슷하면서도 다릅니다.


Name = in.var.NORMAL

Name = in.var.COLOR_1

Name = in.var.OPACITY_512

Name = in.var.SCALE_987654321

Name = in.var.TEXCOORD0

Name = in.var.TEXCOORD1

Name = in.var.TEXCOORD2


그런데 dxc 의 옵션으로 "-fspv-reflect" 를 지정해서 컴파일했다면 정확한 이름/시맨틱 쌍을 얻을 수 있습니다.


Name = in.var.NORMAL

Semantic = NORMAL

Name = in.var.COLOR_1

Semantic = COLOR_00001

Name = in.var.OPACITY_512

Semantic = OPACITY_512

Name = in.var.SCALE_987654321

Semantic = SCALE_987654321

Name = in.var.TEXCOORD0

Semantic = TEXCOORD0

Name = in.var.TEXCOORD1

Semantic = TEXCOORD1

Name = in.var.TEXCOORD2

Semantic = TEXCOORD2


시맨틱을 얻게 되면 다음과 같은 식으로 시맨틱을 사용해서 리플렉션 정보를 획득하는 것도 가능합니다.



사용자들은 맹글링된 이름이 아니라 원래 이름으로 검색하고 싶겠지만, 안타깝게도 그런 방법은 존재하지 않습니다. dxc 에 이런 저런 옵션을 다 넣어서 확인해 봤지만 정보가 안 나오더군요. 만약 필요하다면 dxc 를 커스터마이징하는 수밖에 없는 것 같습니다.


그래도 확실하게 정보가 유지되는 것은 시맨틱이기 때문에 시맨틱을 사용해서 리플렉션을 하는 것이 현명해 보입니다.

+ Recent posts