SPIR-VからHLSLを生成する

提供: MonoBook
ナビゲーションに移動 検索に移動

SPIR-Vから様々なシェーディング言語逆コンパイルできると色々捗ると思われる。 SPIR-VHLSLGLSLから生成できるので相互変換もできることになる。 夢が広がりんぐ

準備[編集 | ソースを編集]

Vulkan SDKSPIR-VからGLSLを生成する逆コンパイラが含まれている。 まずはダウンロードだ。今回はmacOS版をダウンロードしてきた。

Vulkan SDKを展開すると以下に逆コンパイラがある(mac版の場合)。

./macOS/bin/spirv-cross

SPIR-Vファイルは「DirectX Shader CompilerでSPIR-Vを出力する」で生成したものを使った。GLSLではなくHLSLから生成したSPIR-Vファイルだ。


spirv-crossのHLSL変換は「シェーダーモデル3.0以降」をサポートしている。


SM 6.0[編集 | ソースを編集]

実行

./spirv-cross --hlsl --shader-model 60 light_vs.spv

結果。出力用の変数にgl_PositionなどのGLSLのシステム変数名が使われている。なかなか衝撃的なソースコードだ。

cbuffer type_Globals : register(b0, space0)
{
    column_major float4x4 _Globals_WorldViewProjection : packoffset(c0);
};


static float4 gl_Position;
static float4 in_var_POSITION0;
static float4 in_var_COLOR0;
static float4 out_var_COLOR0;

struct SPIRV_Cross_Input
{
    float4 in_var_POSITION0 : TEXCOORD0;
    float4 in_var_COLOR0 : TEXCOORD1;
};

struct SPIRV_Cross_Output
{
    float4 out_var_COLOR0 : TEXCOORD0;
    float4 gl_Position : SV_Position;
};

void vert_main()
{
    gl_Position = mul(in_var_POSITION0, _Globals_WorldViewProjection);
    out_var_COLOR0 = in_var_COLOR0;
}

SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
    in_var_POSITION0 = stage_input.in_var_POSITION0;
    in_var_COLOR0 = stage_input.in_var_COLOR0;
    vert_main();
    SPIRV_Cross_Output stage_output;
    stage_output.gl_Position = gl_Position;
    stage_output.out_var_COLOR0 = out_var_COLOR0;
    return stage_output;
}

SM 3.0[編集 | ソースを編集]

実行

./spirv-cross --hlsl --shader-model 30 light_vs.spv

結果。

cbuffer type_Globals : register(b0)
{
    column_major float4x4 _Globals_WorldViewProjection : packoffset(c0);
};

uniform float4 gl_HalfPixel;

static float4 gl_Position;
static float4 in_var_POSITION0;
static float4 in_var_COLOR0;
static float4 out_var_COLOR0;

struct SPIRV_Cross_Input
{
    float4 in_var_POSITION0 : TEXCOORD0;
    float4 in_var_COLOR0 : TEXCOORD1;
};

struct SPIRV_Cross_Output
{
    float4 out_var_COLOR0 : TEXCOORD0;
    float4 gl_Position : POSITION;
};

void vert_main()
{
    gl_Position = mul(in_var_POSITION0, _Globals_WorldViewProjection);
    out_var_COLOR0 = in_var_COLOR0;
    gl_Position.x = gl_Position.x - gl_HalfPixel.x * gl_Position.w;
    gl_Position.y = gl_Position.y + gl_HalfPixel.y * gl_Position.w;
}

SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
    in_var_POSITION0 = stage_input.in_var_POSITION0;
    in_var_COLOR0 = stage_input.in_var_COLOR0;
    vert_main();
    SPIRV_Cross_Output stage_output;
    stage_output.gl_Position = gl_Position;
    stage_output.out_var_COLOR0 = out_var_COLOR0;
    return stage_output;
}

備考[編集 | ソースを編集]

SPIR-V経由で出力したコードを比較した限りでは以下のような結論に達した。

  • HLSLで書く
  • HLSLはHLSLのまま使う
  • HLSLからGLSLを生成する

比較量は少ないでまだ正確なことは言えないが、 GLSLで書いてHLSLへ変換という逆パターンは危険そうな雰囲気がある。

関連項目[編集 | ソースを編集]