用一张图来说清楚Unreal针对Shader的跨平台处理方案。
[plantuml]
title Unreal cross-platform shader solution\nhttps://tis.ac.cn/blog/kongdeyou/shader_cross_platform_compile_unreal/
partition Source {
  :HLSL>
}
split
  partition DirectX {
    :D3D Compiler;
    split
      partition DX12.1 {
        :DX-IL]
        note right
          MS-DX12.1 LLVM IL
          Device independent
        end note
      }
      kill
    split again
      partition DX11,DX12 {
        :DX-BC]
      }
      kill
    end split
  }
split again
  :HLSLCC;
  note right
    HLSL -> AST -> Mesa IR
    Mesa IR -> Other shader source
  end note
  split
    partition OpenGL {
      :GLSL>
    }
    partition Vulkan {
      :glslang;
      :SPIRV]
    }
    kill
  split again
    partition Metal {
      :Metal SL>
      :MSL Compiler;
      :metallib]
      note left
        Apple Metal LLVM IL
        Device independent
      end note
    }
    kill
  end split
end split
[/plantuml]
最开始的文章中提到过,Unreal的解决方案是Source to Source。
Unreal以HLSL语言作为Shader的源语言。
当平台是DirectX时,直接使用官方的D3D Compiler,对于DX12及以下的版本生成字节码DXBC使用,对于DX12.1,D3D Compiler将生成一个设备无关的中间语言DXIL,微软开源了DXIL,DXIL是一个基于LLVM的中间语言,因此DXIL是个开放标准的字节码系统,不再需要根据DDK来猜测各种文档未定义的行为,DXBC也至此完成了它的历史使命。
当平台为非DirectX时,Unreal实现了一套HLSLCC,用来做Source to Source的转换,将HLSL语言的Shader代码转换为其他语言的Shader代码。HLSLCC是Unreal基于Mesa编译器魔改的,将输入的HLSL代码解析出抽象语法树,再转化为Mesa中间表示语言,最后转化为GLSL或MSL。事实上,这个过程Unreal做了不少的优化。(图形搞来搞去搞到最后在玩编译器啊啊啊…误)
协议
本文以上内容遵循CC BY-ND 4.0协议,署名-禁止演绎。
转载请注明出处:https://tis.ac.cn/blog/kongdeyou/shader_cross_platform_compile_unreal/
并署名:kongdeyou(https://tis.ac.cn/blog/author/kongdeyou/)
 
                 
            