HLSL を入力としたシェーダのトランスコンパイラをやってみたくなったので調べてみました。
準備
DirectXShaderCompiler は Windows SDK に含まれていますが、SPIR-V のコードジェネレータは含まれていないようでした。
なのでコンパイラを自分でビルドします。
前提条件や公式の手順は こちら です。
git clone https://github.com/Microsoft/DirectXShaderCompiler.git
cd DirectXShaderCompiler
git submodule update --init
.\utils\hct\hctstart.cmd <dxc-src-dir> <dxc-bin-dir>
.\utils\hct\hctbuild.cmd -spirv
<dxc-src-dir>
はクローンフォルダ、<dxc-bin-dir>
はビルドのための一時フォルダです。
私の環境では Windows Driver Kit はすでにインストールされていたので、hctgettaef.py の実行はスキップしました。
ビルドが成功すると <dxc-bin-dir>/Debug/bin/dxc.exe
に実行ファイルが出力されます。
変換してみる
HLSLのシェーダを用意します。
test.hlsl
Texture2D txDiffuse : register(t0);
SamplerState samLinear : register(s0);
cbuffer ConstBuff : register(b0)
{
matrix mtxProj;
matrix mtxView;
matrix mtxWorld;
float4 Diffuse;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float2 Tex : TEXCOORD;
};
float4 main(PS_INPUT input) : SV_Target
{
return txDiffuse.Sample(samLinear, input.Tex)*Diffuse;
}
dxc を使って SPIR-V に変換します。
> dxc -spirv -T ps_6_0 -E main test.hlsl -Fo test.spv
spirv-cross を使って GLSL に変換します。(spirv-cross は VulkanSDK に含まれています)
> spirv-cross --version 310 --es test.spv > test.frag
以下のようなコードが出力されました。
test.frag
# version 310 es
precision mediump float;
precision highp int;
layout(binding = 0, std140) uniform type_ConstBuff
{
layout(row_major) highp mat4 mtxProj;
layout(row_major) highp mat4 mtxView;
layout(row_major) highp mat4 mtxWorld;
highp vec4 Diffuse;
} ConstBuff;
uniform highp sampler2D SPIRV_Cross_CombinedtxDiffusesamLinear;
layout(location = 0) in highp vec2 in_var_TEXCOORD;
layout(location = 0) out highp vec4 out_var_SV_Target;
void main()
{
out_var_SV_Target = texture(SPIRV_Cross_CombinedtxDiffusesamLinear, in_var_TEXCOORD) * ConstBuff.Diffuse;
}