Implement unorm16/snorm16 packing in HLSL.

This commit is contained in:
Hans-Kristian Arntzen 2017-11-27 15:03:40 +01:00
Родитель 719ba63416
Коммит 656af7e3ed
5 изменённых файлов: 171 добавлений и 3 удалений

Просмотреть файл

@ -1,15 +1,21 @@
static float4 FP32Out;
static uint UNORM8;
static uint SNORM8;
static uint UNORM16;
static uint SNORM16;
static uint UNORM8Out;
static float4 FP32;
static uint SNORM8Out;
static uint UNORM16Out;
static uint SNORM16Out;
struct SPIRV_Cross_Input
{
nointerpolation uint SNORM8 : TEXCOORD0;
nointerpolation uint UNORM8 : TEXCOORD1;
nointerpolation float4 FP32 : TEXCOORD2;
nointerpolation uint SNORM16 : TEXCOORD2;
nointerpolation uint UNORM16 : TEXCOORD3;
nointerpolation float4 FP32 : TEXCOORD4;
};
struct SPIRV_Cross_Output
@ -17,6 +23,8 @@ struct SPIRV_Cross_Output
float4 FP32Out : SV_Target0;
uint UNORM8Out : SV_Target1;
uint SNORM8Out : SV_Target2;
uint UNORM16Out : SV_Target3;
uint SNORM16Out : SV_Target4;
};
uint SPIRV_Cross_packUnorm4x8(float4 value)
@ -44,23 +52,58 @@ float4 SPIRV_Cross_unpackSnorm4x8(uint value)
return clamp(float4(Packed) / 127.0, -1.0, 1.0);
}
uint SPIRV_Cross_packUnorm2x16(float2 value)
{
uint2 Packed = uint2(round(saturate(value) * 65535.0));
return Packed.x | (Packed.y << 16);
}
float2 SPIRV_Cross_unpackUnorm2x16(uint value)
{
uint2 Packed = uint2(value & 0xffff, value >> 16);
return float2(Packed) / 65535.0;
}
uint SPIRV_Cross_packSnorm2x16(float2 value)
{
int2 Packed = int2(round(clamp(value, -1.0, 1.0) * 32767.0)) & 0xffff;
return uint(Packed.x | (Packed.y << 16));
}
float2 SPIRV_Cross_unpackSnorm2x16(uint value)
{
int SignedValue = int(value);
int2 Packed = int2(SignedValue << 16, SignedValue) >> 16;
return clamp(float2(Packed) / 32767.0, -1.0, 1.0);
}
void frag_main()
{
FP32Out = SPIRV_Cross_unpackUnorm4x8(UNORM8);
FP32Out = SPIRV_Cross_unpackSnorm4x8(SNORM8);
float2 _21 = SPIRV_Cross_unpackUnorm2x16(UNORM16);
FP32Out = float4(_21.x, _21.y, FP32Out.z, FP32Out.w);
float2 _26 = SPIRV_Cross_unpackSnorm2x16(SNORM16);
FP32Out = float4(_26.x, _26.y, FP32Out.z, FP32Out.w);
UNORM8Out = SPIRV_Cross_packUnorm4x8(FP32);
SNORM8Out = SPIRV_Cross_packSnorm4x8(FP32);
UNORM16Out = SPIRV_Cross_packUnorm2x16(FP32.xy);
SNORM16Out = SPIRV_Cross_packSnorm2x16(FP32.zw);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
UNORM8 = stage_input.UNORM8;
SNORM8 = stage_input.SNORM8;
UNORM16 = stage_input.UNORM16;
SNORM16 = stage_input.SNORM16;
FP32 = stage_input.FP32;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FP32Out = FP32Out;
stage_output.UNORM8Out = UNORM8Out;
stage_output.SNORM8Out = SNORM8Out;
stage_output.UNORM16Out = UNORM16Out;
stage_output.SNORM16Out = SNORM16Out;
return stage_output;
}

Просмотреть файл

@ -1,15 +1,21 @@
static float4 FP32Out;
static uint UNORM8;
static uint SNORM8;
static uint UNORM16;
static uint SNORM16;
static uint UNORM8Out;
static float4 FP32;
static uint SNORM8Out;
static uint UNORM16Out;
static uint SNORM16Out;
struct SPIRV_Cross_Input
{
nointerpolation uint SNORM8 : TEXCOORD0;
nointerpolation uint UNORM8 : TEXCOORD1;
nointerpolation float4 FP32 : TEXCOORD2;
nointerpolation uint SNORM16 : TEXCOORD2;
nointerpolation uint UNORM16 : TEXCOORD3;
nointerpolation float4 FP32 : TEXCOORD4;
};
struct SPIRV_Cross_Output
@ -17,6 +23,8 @@ struct SPIRV_Cross_Output
float4 FP32Out : SV_Target0;
uint UNORM8Out : SV_Target1;
uint SNORM8Out : SV_Target2;
uint UNORM16Out : SV_Target3;
uint SNORM16Out : SV_Target4;
};
uint SPIRV_Cross_packUnorm4x8(float4 value)
@ -44,23 +52,58 @@ float4 SPIRV_Cross_unpackSnorm4x8(uint value)
return clamp(float4(Packed) / 127.0, -1.0, 1.0);
}
uint SPIRV_Cross_packUnorm2x16(float2 value)
{
uint2 Packed = uint2(round(saturate(value) * 65535.0));
return Packed.x | (Packed.y << 16);
}
float2 SPIRV_Cross_unpackUnorm2x16(uint value)
{
uint2 Packed = uint2(value & 0xffff, value >> 16);
return float2(Packed) / 65535.0;
}
uint SPIRV_Cross_packSnorm2x16(float2 value)
{
int2 Packed = int2(round(clamp(value, -1.0, 1.0) * 32767.0)) & 0xffff;
return uint(Packed.x | (Packed.y << 16));
}
float2 SPIRV_Cross_unpackSnorm2x16(uint value)
{
int SignedValue = int(value);
int2 Packed = int2(SignedValue << 16, SignedValue) >> 16;
return clamp(float2(Packed) / 32767.0, -1.0, 1.0);
}
void frag_main()
{
FP32Out = SPIRV_Cross_unpackUnorm4x8(UNORM8);
FP32Out = SPIRV_Cross_unpackSnorm4x8(SNORM8);
float2 _21 = SPIRV_Cross_unpackUnorm2x16(UNORM16);
FP32Out = float4(_21.x, _21.y, FP32Out.z, FP32Out.w);
float2 _26 = SPIRV_Cross_unpackSnorm2x16(SNORM16);
FP32Out = float4(_26.x, _26.y, FP32Out.z, FP32Out.w);
UNORM8Out = SPIRV_Cross_packUnorm4x8(FP32);
SNORM8Out = SPIRV_Cross_packSnorm4x8(FP32);
UNORM16Out = SPIRV_Cross_packUnorm2x16(FP32.xy);
SNORM16Out = SPIRV_Cross_packSnorm2x16(FP32.zw);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
UNORM8 = stage_input.UNORM8;
SNORM8 = stage_input.SNORM8;
UNORM16 = stage_input.UNORM16;
SNORM16 = stage_input.SNORM16;
FP32 = stage_input.FP32;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FP32Out = FP32Out;
stage_output.UNORM8Out = UNORM8Out;
stage_output.SNORM8Out = SNORM8Out;
stage_output.UNORM16Out = UNORM16Out;
stage_output.SNORM16Out = SNORM16Out;
return stage_output;
}

Просмотреть файл

@ -2,15 +2,23 @@
layout(location = 0) flat in uint SNORM8;
layout(location = 1) flat in uint UNORM8;
layout(location = 2) flat in vec4 FP32;
layout(location = 2) flat in uint SNORM16;
layout(location = 3) flat in uint UNORM16;
layout(location = 4) flat in vec4 FP32;
layout(location = 0) out vec4 FP32Out;
layout(location = 1) out uint UNORM8Out;
layout(location = 2) out uint SNORM8Out;
layout(location = 3) out uint UNORM16Out;
layout(location = 4) out uint SNORM16Out;
void main()
{
FP32Out = unpackUnorm4x8(UNORM8);
FP32Out = unpackSnorm4x8(SNORM8);
FP32Out.xy = unpackUnorm2x16(UNORM16);
FP32Out.xy = unpackSnorm2x16(SNORM16);
UNORM8Out = packUnorm4x8(FP32);
SNORM8Out = packSnorm4x8(FP32);
UNORM16Out = packUnorm2x16(FP32.xy);
SNORM16Out = packSnorm2x16(FP32.zw);
}

Просмотреть файл

@ -1201,6 +1201,7 @@ void CompilerHLSL::emit_resources()
statement("");
}
// HLSL does not seem to have builtins for these operation, so roll them by hand ...
if (requires_unorm8_packing)
{
statement("uint SPIRV_Cross_packUnorm4x8(float4 value)");
@ -1235,6 +1236,41 @@ void CompilerHLSL::emit_resources()
end_scope();
statement("");
}
if (requires_unorm16_packing)
{
statement("uint SPIRV_Cross_packUnorm2x16(float2 value)");
begin_scope();
statement("uint2 Packed = uint2(round(saturate(value) * 65535.0));");
statement("return Packed.x | (Packed.y << 16);");
end_scope();
statement("");
statement("float2 SPIRV_Cross_unpackUnorm2x16(uint value)");
begin_scope();
statement("uint2 Packed = uint2(value & 0xffff, value >> 16);");
statement("return float2(Packed) / 65535.0;");
end_scope();
statement("");
}
if (requires_snorm16_packing)
{
statement("uint SPIRV_Cross_packSnorm2x16(float2 value)");
begin_scope();
statement("int2 Packed = int2(round(clamp(value, -1.0, 1.0) * 32767.0)) & 0xffff;");
statement("return uint(Packed.x | (Packed.y << 16));");
end_scope();
statement("");
statement("float2 SPIRV_Cross_unpackSnorm2x16(uint value)");
begin_scope();
statement("int SignedValue = int(value);");
statement("int2 Packed = int2(SignedValue << 16, SignedValue) >> 16;");
statement("return clamp(float2(Packed) / 32767.0, -1.0, 1.0);");
end_scope();
statement("");
}
}
string CompilerHLSL::layout_for_member(const SPIRType &type, uint32_t index)
@ -2315,6 +2351,42 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackUnorm4x8");
break;
case GLSLstd450PackSnorm2x16:
if (!requires_snorm16_packing)
{
requires_snorm16_packing = true;
force_recompile = true;
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packSnorm2x16");
break;
case GLSLstd450UnpackSnorm2x16:
if (!requires_snorm16_packing)
{
requires_snorm16_packing = true;
force_recompile = true;
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackSnorm2x16");
break;
case GLSLstd450PackUnorm2x16:
if (!requires_unorm16_packing)
{
requires_unorm16_packing = true;
force_recompile = true;
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_packUnorm2x16");
break;
case GLSLstd450UnpackUnorm2x16:
if (!requires_unorm16_packing)
{
requires_unorm16_packing = true;
force_recompile = true;
}
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_unpackUnorm2x16");
break;
default:
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
break;

Просмотреть файл

@ -119,6 +119,8 @@ private:
bool requires_fp16_packing = false;
bool requires_unorm8_packing = false;
bool requires_snorm8_packing = false;
bool requires_unorm16_packing = false;
bool requires_snorm16_packing = false;
uint64_t required_textureSizeVariants = 0;
void require_texture_query_variant(const SPIRType &type);