Implement FP16 unpack/pack on HLSL.

This commit is contained in:
Hans-Kristian Arntzen 2017-11-27 14:24:30 +01:00
parent 5989540f3e
commit 6c7c680d01
5 changed files with 135 additions and 0 deletions

View File

@ -0,0 +1,44 @@
static float2 FP32Out;
static uint FP16;
static uint FP16Out;
static float2 FP32;
struct SPIRV_Cross_Input
{
nointerpolation uint FP16 : TEXCOORD0;
nointerpolation float2 FP32 : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float2 FP32Out : SV_Target0;
uint FP16Out : SV_Target1;
};
uint SPIRV_Cross_packHalf2x16(float2 value)
{
uint2 Packed = f32tof16(value);
return Packed.x | (Packed.y << 16);
}
float2 SPIRV_Cross_unpackHalf2x16(uint value)
{
return f16tof32(uint2(value & 0xffff, value >> 16));
}
void frag_main()
{
FP32Out = SPIRV_Cross_unpackHalf2x16(FP16);
FP16Out = SPIRV_Cross_packHalf2x16(FP32);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
FP16 = stage_input.FP16;
FP32 = stage_input.FP32;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FP32Out = FP32Out;
stage_output.FP16Out = FP16Out;
return stage_output;
}

View File

@ -0,0 +1,44 @@
static float2 FP32Out;
static uint FP16;
static uint FP16Out;
static float2 FP32;
struct SPIRV_Cross_Input
{
nointerpolation uint FP16 : TEXCOORD0;
nointerpolation float2 FP32 : TEXCOORD1;
};
struct SPIRV_Cross_Output
{
float2 FP32Out : SV_Target0;
uint FP16Out : SV_Target1;
};
uint SPIRV_Cross_packHalf2x16(float2 value)
{
uint2 Packed = f32tof16(value);
return Packed.x | (Packed.y << 16);
}
float2 SPIRV_Cross_unpackHalf2x16(uint value)
{
return f16tof32(uint2(value & 0xffff, value >> 16));
}
void frag_main()
{
FP32Out = SPIRV_Cross_unpackHalf2x16(FP16);
FP16Out = SPIRV_Cross_packHalf2x16(FP32);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
FP16 = stage_input.FP16;
FP32 = stage_input.FP32;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FP32Out = FP32Out;
stage_output.FP16Out = FP16Out;
return stage_output;
}

View File

@ -0,0 +1,12 @@
#version 450
layout(location = 0) flat in uint FP16;
layout(location = 1) flat in vec2 FP32;
layout(location = 0) out vec2 FP32Out;
layout(location = 1) out uint FP16Out;
void main()
{
FP32Out = unpackHalf2x16(FP16);
FP16Out = packHalf2x16(FP32);
}

View File

@ -1183,6 +1183,22 @@ void CompilerHLSL::emit_resources()
}
}
}
if (requires_fp16_packing)
{
statement("uint SPIRV_Cross_packHalf2x16(float2 value)");
begin_scope();
statement("uint2 Packed = f32tof16(value);");
statement("return Packed.x | (Packed.y << 16);");
end_scope();
statement("");
statement("float2 SPIRV_Cross_unpackHalf2x16(uint value)");
begin_scope();
statement("return f16tof32(uint2(value & 0xffff, value >> 16));");
end_scope();
statement("");
}
}
string CompilerHLSL::layout_for_member(const SPIRType &type, uint32_t index)
@ -2209,6 +2225,24 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
emit_binary_func_op(result_type, id, args[0], args[1], "EvaluateAttributeSnapped");
break;
case GLSLstd450PackHalf2x16:
if (!requires_fp16_packing)
{
requires_fp16_packing = true;
force_recompile = true;
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packHalf2x16");
break;
case GLSLstd450UnpackHalf2x16:
if (!requires_fp16_packing)
{
requires_fp16_packing = true;
force_recompile = true;
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackHalf2x16");
break;
default:
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
break;

View File

@ -116,6 +116,7 @@ private:
Options options;
bool requires_op_fmod = false;
bool requires_textureProj = false;
bool requires_fp16_packing = false;
uint64_t required_textureSizeVariants = 0;
void require_texture_query_variant(const SPIRType &type);