diff --git a/reference/shaders-hlsl/frag/builtins.frag b/reference/shaders-hlsl/frag/builtins.frag new file mode 100644 index 0000000..9014edf --- /dev/null +++ b/reference/shaders-hlsl/frag/builtins.frag @@ -0,0 +1,33 @@ +static float4 gl_FragCoord; +static float gl_FragDepth; +static float4 FragColor; +static float4 vColor; + +struct SPIRV_Cross_Input +{ + float4 gl_FragCoord : VPOS; + float4 vColor : TEXCOORD0; +}; + +struct SPIRV_Cross_Output +{ + float gl_FragDepth : DEPTH; + float4 FragColor : COLOR0; +}; + +void frag_main() +{ + FragColor = gl_FragCoord + vColor; + gl_FragDepth = 0.5f; +} + +SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input) +{ + gl_FragCoord = stage_input.gl_FragCoord + float4(0.5f, 0.5f, 0.0f, 0.0f); + vColor = stage_input.vColor; + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.gl_FragDepth = gl_FragDepth; + stage_output.FragColor = FragColor; + return stage_output; +} diff --git a/shaders-hlsl/frag/builtins.frag b/shaders-hlsl/frag/builtins.frag new file mode 100644 index 0000000..99e6e2d --- /dev/null +++ b/shaders-hlsl/frag/builtins.frag @@ -0,0 +1,11 @@ +#version 310 es +precision mediump float; + +layout(location = 0) out vec4 FragColor; +layout(location = 0) in vec4 vColor; + +void main() +{ + FragColor = gl_FragCoord + vColor; + gl_FragDepth = 0.5; +} diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index 6f11cbe..bee89db 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -165,6 +165,11 @@ void CompilerHLSL::emit_builtin_outputs_in_struct() semantic = legacy ? "POSITION" : "SV_Position"; break; + case BuiltInFragDepth: + type = "float"; + semantic = legacy ? "DEPTH" : "SV_Depth"; + break; + default: SPIRV_CROSS_THROW("Unsupported builtin in HLSL."); break; @@ -190,7 +195,21 @@ void CompilerHLSL::emit_builtin_inputs_in_struct() { case BuiltInFragCoord: type = "float4"; - semantic = legacy ? "POSITION" : "SV_Position"; + semantic = legacy ? "VPOS" : "SV_Position"; + break; + + case BuiltInVertexIndex: + if (legacy) + SPIRV_CROSS_THROW("Vertex index not supported in SM 3.0 or lower."); + type = "uint"; + semantic = "SV_VertexID"; + break; + + case BuiltInInstanceIndex: + if (legacy) + SPIRV_CROSS_THROW("Vertex index not supported in SM 3.0 or lower."); + type = "uint"; + semantic = "SV_InstanceID"; break; default: @@ -308,6 +327,15 @@ void CompilerHLSL::emit_builtin_variables() type = "float4"; break; + case BuiltInFragDepth: + type = "float"; + break; + + case BuiltInVertexIndex: + case BuiltInInstanceIndex: + type = "int"; + break; + default: SPIRV_CROSS_THROW(join("Unsupported builtin in HLSL: ", unsigned(builtin))); break; @@ -630,21 +658,43 @@ void CompilerHLSL::emit_hlsl_entry_point() statement(require_output ? "SPIRV_Cross_Output " : "void ", "main(", require_input ? "SPIRV_Cross_Input stage_input)" : ")"); begin_scope(); + bool legacy = options.shader_model <= 30; if (require_input) { + // Copy builtins from entry point arguments to globals. + for (uint32_t i = 0; i < 64; i++) + { + if (!(active_input_builtins & (1ull << i))) + continue; + + auto builtin = builtin_to_glsl(static_cast(i)); + switch (static_cast(i)) + { + case BuiltInFragCoord: + // VPOS in D3D9 is sampled at integer locations, apply half-pixel offset to be consistent. + // TODO: Do we need an option here? Any reason why a D3D9 shader would be used + // on a D3D10+ system? + if (legacy) + statement(builtin, " = stage_input.", builtin, " + float4(0.5f, 0.5f, 0.0f, 0.0f);"); + else + statement(builtin, " = stage_input.", builtin, ";"); + break; + + case BuiltInVertexIndex: + case BuiltInInstanceIndex: + // D3D semantics are uint, but shader wants int. + statement(builtin, " = int(stage_input.", builtin, ");"); + break; + + default: + statement(builtin, " = stage_input.", builtin, ";"); + break; + } + } + for (auto &id : ids) { - // Copy builtins from entry point arguments to globals. - for (uint32_t i = 0; i < 64; i++) - { - if (!(active_input_builtins & (1ull << i))) - continue; - - auto builtin = builtin_to_glsl(static_cast(i)); - statement(builtin, " = stage_input.", builtin, ";"); - } - if (id.get_type() == TypeVariable) { auto &var = id.get(); @@ -656,12 +706,11 @@ void CompilerHLSL::emit_hlsl_entry_point() { auto name = to_name(var.self); auto &mtype = get(var.basetype); - if (mtype.vecsize == 4 && mtype.columns == 4) + if (mtype.columns > 1) { - statement(name, "[0] = stage_input.", name, "_0;"); - statement(name, "[1] = stage_input.", name, "_1;"); - statement(name, "[2] = stage_input.", name, "_2;"); - statement(name, "[3] = stage_input.", name, "_3;"); + // Unroll matrices. + for (uint32_t col = 0; col < mtype.columns; col++) + statement(name, "[", col, "] = stage_input.", name, "_0;"); } else {