yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Shader_Ir: Implement F16 Variants of F2F, F2I, I2F.

This commit takes care of implementing the F16 Variants of the 
conversion instructions and makes sure conversions are done.
This commit is contained in:
Fernando Sahmkow 2019-07-20 17:38:25 -04:00
parent 0a67416971
commit 11f4e739bd
5 changed files with 75 additions and 18 deletions

View File

@ -1018,8 +1018,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

View File

@ -1122,6 +1122,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);
@ -1278,6 +1288,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 {
@ -1718,6 +1733,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,
@ -1778,6 +1795,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,

View File

@ -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,

View File

@ -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 = [&]() {

View File

@ -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