Merge pull request #2753 from FernandoS27/float-convert

Shader_Ir: Implement F16 Variants of F2F, F2I, I2F.
master
bunnei 2019-08-21 10:27:57 +07:00 committed by GitHub
commit cedc1aab4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 18 deletions

@ -1023,8 +1023,6 @@ union Instruction {
} f2i; } f2i;
union { union {
BitField<8, 2, Register::Size> src_size;
BitField<10, 2, Register::Size> dst_size;
BitField<39, 4, u64> rounding; BitField<39, 4, u64> rounding;
// H0, H1 extract for F16 missing // H0, H1 extract for F16 missing
BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value

@ -1136,6 +1136,16 @@ private:
Type::Float); Type::Float);
} }
std::string FCastHalf0(Operation operation) {
const std::string op_a = VisitOperand(operation, 0, Type::HalfFloat);
return fmt::format("({})[0]", op_a);
}
std::string FCastHalf1(Operation operation) {
const std::string op_a = VisitOperand(operation, 0, Type::HalfFloat);
return fmt::format("({})[1]", op_a);
}
template <Type type> template <Type type>
std::string Min(Operation operation) { std::string Min(Operation operation) {
return GenerateBinaryCall(operation, "min", type, type, type); return GenerateBinaryCall(operation, "min", type, type, type);
@ -1292,6 +1302,11 @@ private:
return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat)); return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat));
} }
std::string HCastFloat(Operation operation) {
const std::string op_a = VisitOperand(operation, 0, Type::Float);
return fmt::format("fromHalf2(vec2({}, 0.0f))", op_a);
}
std::string HUnpack(Operation operation) { std::string HUnpack(Operation operation) {
const std::string operand{VisitOperand(operation, 0, Type::HalfFloat)}; const std::string operand{VisitOperand(operation, 0, Type::HalfFloat)};
const auto value = [&]() -> std::string { const auto value = [&]() -> std::string {
@ -1732,6 +1747,8 @@ private:
&GLSLDecompiler::Negate<Type::Float>, &GLSLDecompiler::Negate<Type::Float>,
&GLSLDecompiler::Absolute<Type::Float>, &GLSLDecompiler::Absolute<Type::Float>,
&GLSLDecompiler::FClamp, &GLSLDecompiler::FClamp,
&GLSLDecompiler::FCastHalf0,
&GLSLDecompiler::FCastHalf1,
&GLSLDecompiler::Min<Type::Float>, &GLSLDecompiler::Min<Type::Float>,
&GLSLDecompiler::Max<Type::Float>, &GLSLDecompiler::Max<Type::Float>,
&GLSLDecompiler::FCos, &GLSLDecompiler::FCos,
@ -1792,6 +1809,7 @@ private:
&GLSLDecompiler::Absolute<Type::HalfFloat>, &GLSLDecompiler::Absolute<Type::HalfFloat>,
&GLSLDecompiler::HNegate, &GLSLDecompiler::HNegate,
&GLSLDecompiler::HClamp, &GLSLDecompiler::HClamp,
&GLSLDecompiler::HCastFloat,
&GLSLDecompiler::HUnpack, &GLSLDecompiler::HUnpack,
&GLSLDecompiler::HMergeF32, &GLSLDecompiler::HMergeF32,
&GLSLDecompiler::HMergeH0, &GLSLDecompiler::HMergeH0,

@ -735,6 +735,16 @@ private:
return {}; return {};
} }
Id FCastHalf0(Operation operation) {
UNIMPLEMENTED();
return {};
}
Id FCastHalf1(Operation operation) {
UNIMPLEMENTED();
return {};
}
Id HNegate(Operation operation) { Id HNegate(Operation operation) {
UNIMPLEMENTED(); UNIMPLEMENTED();
return {}; return {};
@ -745,6 +755,11 @@ private:
return {}; return {};
} }
Id HCastFloat(Operation operation) {
UNIMPLEMENTED();
return {};
}
Id HUnpack(Operation operation) { Id HUnpack(Operation operation) {
UNIMPLEMENTED(); UNIMPLEMENTED();
return {}; return {};
@ -1210,6 +1225,8 @@ private:
&SPIRVDecompiler::Unary<&Module::OpFNegate, Type::Float>, &SPIRVDecompiler::Unary<&Module::OpFNegate, Type::Float>,
&SPIRVDecompiler::Unary<&Module::OpFAbs, Type::Float>, &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::Float>,
&SPIRVDecompiler::Ternary<&Module::OpFClamp, Type::Float>, &SPIRVDecompiler::Ternary<&Module::OpFClamp, Type::Float>,
&SPIRVDecompiler::FCastHalf0,
&SPIRVDecompiler::FCastHalf1,
&SPIRVDecompiler::Binary<&Module::OpFMin, Type::Float>, &SPIRVDecompiler::Binary<&Module::OpFMin, Type::Float>,
&SPIRVDecompiler::Binary<&Module::OpFMax, Type::Float>, &SPIRVDecompiler::Binary<&Module::OpFMax, Type::Float>,
&SPIRVDecompiler::Unary<&Module::OpCos, Type::Float>, &SPIRVDecompiler::Unary<&Module::OpCos, Type::Float>,
@ -1270,6 +1287,7 @@ private:
&SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>, &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>,
&SPIRVDecompiler::HNegate, &SPIRVDecompiler::HNegate,
&SPIRVDecompiler::HClamp, &SPIRVDecompiler::HClamp,
&SPIRVDecompiler::HCastFloat,
&SPIRVDecompiler::HUnpack, &SPIRVDecompiler::HUnpack,
&SPIRVDecompiler::HMergeF32, &SPIRVDecompiler::HMergeF32,
&SPIRVDecompiler::HMergeH0, &SPIRVDecompiler::HMergeH0,

@ -57,7 +57,7 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
case OpCode::Id::I2F_R: case OpCode::Id::I2F_R:
case OpCode::Id::I2F_C: case OpCode::Id::I2F_C:
case OpCode::Id::I2F_IMM: { case OpCode::Id::I2F_IMM: {
UNIMPLEMENTED_IF(instr.conversion.dst_size != Register::Size::Word); UNIMPLEMENTED_IF(instr.conversion.dst_size == Register::Size::Long);
UNIMPLEMENTED_IF(instr.conversion.selector); UNIMPLEMENTED_IF(instr.conversion.selector);
UNIMPLEMENTED_IF_MSG(instr.generates_cc, UNIMPLEMENTED_IF_MSG(instr.generates_cc,
"Condition codes generation in I2F is not implemented"); "Condition codes generation in I2F is not implemented");
@ -82,14 +82,19 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
value = GetOperandAbsNegFloat(value, false, instr.conversion.negate_a); value = GetOperandAbsNegFloat(value, false, instr.conversion.negate_a);
SetInternalFlagsFromFloat(bb, value, instr.generates_cc); SetInternalFlagsFromFloat(bb, value, instr.generates_cc);
if (instr.conversion.dst_size == Register::Size::Short) {
value = Operation(OperationCode::HCastFloat, PRECISE, value);
}
SetRegister(bb, instr.gpr0, value); SetRegister(bb, instr.gpr0, value);
break; break;
} }
case OpCode::Id::F2F_R: case OpCode::Id::F2F_R:
case OpCode::Id::F2F_C: case OpCode::Id::F2F_C:
case OpCode::Id::F2F_IMM: { case OpCode::Id::F2F_IMM: {
UNIMPLEMENTED_IF(instr.conversion.f2f.dst_size != Register::Size::Word); UNIMPLEMENTED_IF(instr.conversion.dst_size == Register::Size::Long);
UNIMPLEMENTED_IF(instr.conversion.f2f.src_size != Register::Size::Word); UNIMPLEMENTED_IF(instr.conversion.src_size == Register::Size::Long);
UNIMPLEMENTED_IF_MSG(instr.generates_cc, UNIMPLEMENTED_IF_MSG(instr.generates_cc,
"Condition codes generation in F2F is not implemented"); "Condition codes generation in F2F is not implemented");
@ -107,6 +112,11 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
} }
}(); }();
if (instr.conversion.src_size == Register::Size::Short) {
// TODO: figure where extract is sey in the encoding
value = Operation(OperationCode::FCastHalf0, PRECISE, value);
}
value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a);
value = [&]() { value = [&]() {
@ -124,19 +134,24 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
default: default:
UNIMPLEMENTED_MSG("Unimplemented F2F rounding mode {}", UNIMPLEMENTED_MSG("Unimplemented F2F rounding mode {}",
static_cast<u32>(instr.conversion.f2f.rounding.Value())); static_cast<u32>(instr.conversion.f2f.rounding.Value()));
return Immediate(0); return value;
} }
}(); }();
value = GetSaturatedFloat(value, instr.alu.saturate_d); value = GetSaturatedFloat(value, instr.alu.saturate_d);
SetInternalFlagsFromFloat(bb, value, instr.generates_cc); SetInternalFlagsFromFloat(bb, value, instr.generates_cc);
if (instr.conversion.dst_size == Register::Size::Short) {
value = Operation(OperationCode::HCastFloat, PRECISE, value);
}
SetRegister(bb, instr.gpr0, value); SetRegister(bb, instr.gpr0, value);
break; break;
} }
case OpCode::Id::F2I_R: case OpCode::Id::F2I_R:
case OpCode::Id::F2I_C: case OpCode::Id::F2I_C:
case OpCode::Id::F2I_IMM: { case OpCode::Id::F2I_IMM: {
UNIMPLEMENTED_IF(instr.conversion.src_size != Register::Size::Word); UNIMPLEMENTED_IF(instr.conversion.src_size == Register::Size::Long);
UNIMPLEMENTED_IF_MSG(instr.generates_cc, UNIMPLEMENTED_IF_MSG(instr.generates_cc,
"Condition codes generation in F2I is not implemented"); "Condition codes generation in F2I is not implemented");
Node value = [&]() { Node value = [&]() {
@ -153,6 +168,11 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
} }
}(); }();
if (instr.conversion.src_size == Register::Size::Short) {
// TODO: figure where extract is sey in the encoding
value = Operation(OperationCode::FCastHalf0, PRECISE, value);
}
value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a);
value = [&]() { value = [&]() {

@ -30,6 +30,8 @@ enum class OperationCode {
FNegate, /// (MetaArithmetic, float a) -> float FNegate, /// (MetaArithmetic, float a) -> float
FAbsolute, /// (MetaArithmetic, float a) -> float FAbsolute, /// (MetaArithmetic, float a) -> float
FClamp, /// (MetaArithmetic, float value, float min, float max) -> float FClamp, /// (MetaArithmetic, float value, float min, float max) -> float
FCastHalf0, /// (MetaArithmetic, f16vec2 a) -> float
FCastHalf1, /// (MetaArithmetic, f16vec2 a) -> float
FMin, /// (MetaArithmetic, float a, float b) -> float FMin, /// (MetaArithmetic, float a, float b) -> float
FMax, /// (MetaArithmetic, float a, float b) -> float FMax, /// (MetaArithmetic, float a, float b) -> float
FCos, /// (MetaArithmetic, float a) -> float FCos, /// (MetaArithmetic, float a) -> float
@ -83,17 +85,18 @@ enum class OperationCode {
UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
UBitCount, /// (MetaArithmetic, uint) -> uint UBitCount, /// (MetaArithmetic, uint) -> uint
HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 HAdd, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2 HMul, /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 HFma, /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
HAbsolute, /// (f16vec2 a) -> f16vec2 HAbsolute, /// (f16vec2 a) -> f16vec2
HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2
HClamp, /// (f16vec2 src, float min, float max) -> f16vec2 HClamp, /// (f16vec2 src, float min, float max) -> f16vec2
HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2 HCastFloat, /// (MetaArithmetic, float a) -> f16vec2
HMergeF32, /// (f16vec2 src) -> float HUnpack, /// (Tegra::Shader::HalfType, T value) -> f16vec2
HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 HMergeF32, /// (f16vec2 src) -> float
HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
HPack2, /// (float a, float b) -> f16vec2 HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
HPack2, /// (float a, float b) -> f16vec2
LogicalAssign, /// (bool& dst, bool src) -> void LogicalAssign, /// (bool& dst, bool src) -> void
LogicalAnd, /// (bool a, bool b) -> bool LogicalAnd, /// (bool a, bool b) -> bool