Merge pull request #2753 from FernandoS27/float-convert
Shader_Ir: Implement F16 Variants of F2F, F2I, I2F.
This commit is contained in:
		
						commit
						cedc1aab4a
					
				@ -1023,8 +1023,6 @@ union Instruction {
 | 
			
		||||
        } f2i;
 | 
			
		||||
 | 
			
		||||
        union {
 | 
			
		||||
            BitField<8, 2, Register::Size> src_size;
 | 
			
		||||
            BitField<10, 2, Register::Size> dst_size;
 | 
			
		||||
            BitField<39, 4, u64> rounding;
 | 
			
		||||
            // H0, H1 extract for F16 missing
 | 
			
		||||
            BitField<41, 1, u64> selector; // Guessed as some games set it, TODO: reverse this value
 | 
			
		||||
 | 
			
		||||
@ -1136,6 +1136,16 @@ private:
 | 
			
		||||
                               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>
 | 
			
		||||
    std::string Min(Operation operation) {
 | 
			
		||||
        return GenerateBinaryCall(operation, "min", type, type, type);
 | 
			
		||||
@ -1292,6 +1302,11 @@ private:
 | 
			
		||||
        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) {
 | 
			
		||||
        const std::string operand{VisitOperand(operation, 0, Type::HalfFloat)};
 | 
			
		||||
        const auto value = [&]() -> std::string {
 | 
			
		||||
@ -1732,6 +1747,8 @@ private:
 | 
			
		||||
        &GLSLDecompiler::Negate<Type::Float>,
 | 
			
		||||
        &GLSLDecompiler::Absolute<Type::Float>,
 | 
			
		||||
        &GLSLDecompiler::FClamp,
 | 
			
		||||
        &GLSLDecompiler::FCastHalf0,
 | 
			
		||||
        &GLSLDecompiler::FCastHalf1,
 | 
			
		||||
        &GLSLDecompiler::Min<Type::Float>,
 | 
			
		||||
        &GLSLDecompiler::Max<Type::Float>,
 | 
			
		||||
        &GLSLDecompiler::FCos,
 | 
			
		||||
@ -1792,6 +1809,7 @@ private:
 | 
			
		||||
        &GLSLDecompiler::Absolute<Type::HalfFloat>,
 | 
			
		||||
        &GLSLDecompiler::HNegate,
 | 
			
		||||
        &GLSLDecompiler::HClamp,
 | 
			
		||||
        &GLSLDecompiler::HCastFloat,
 | 
			
		||||
        &GLSLDecompiler::HUnpack,
 | 
			
		||||
        &GLSLDecompiler::HMergeF32,
 | 
			
		||||
        &GLSLDecompiler::HMergeH0,
 | 
			
		||||
 | 
			
		||||
@ -735,6 +735,16 @@ private:
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Id FCastHalf0(Operation operation) {
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Id FCastHalf1(Operation operation) {
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Id HNegate(Operation operation) {
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
        return {};
 | 
			
		||||
@ -745,6 +755,11 @@ private:
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Id HCastFloat(Operation operation) {
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
        return {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Id HUnpack(Operation operation) {
 | 
			
		||||
        UNIMPLEMENTED();
 | 
			
		||||
        return {};
 | 
			
		||||
@ -1210,6 +1225,8 @@ private:
 | 
			
		||||
        &SPIRVDecompiler::Unary<&Module::OpFNegate, Type::Float>,
 | 
			
		||||
        &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::Float>,
 | 
			
		||||
        &SPIRVDecompiler::Ternary<&Module::OpFClamp, Type::Float>,
 | 
			
		||||
        &SPIRVDecompiler::FCastHalf0,
 | 
			
		||||
        &SPIRVDecompiler::FCastHalf1,
 | 
			
		||||
        &SPIRVDecompiler::Binary<&Module::OpFMin, Type::Float>,
 | 
			
		||||
        &SPIRVDecompiler::Binary<&Module::OpFMax, Type::Float>,
 | 
			
		||||
        &SPIRVDecompiler::Unary<&Module::OpCos, Type::Float>,
 | 
			
		||||
@ -1270,6 +1287,7 @@ private:
 | 
			
		||||
        &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>,
 | 
			
		||||
        &SPIRVDecompiler::HNegate,
 | 
			
		||||
        &SPIRVDecompiler::HClamp,
 | 
			
		||||
        &SPIRVDecompiler::HCastFloat,
 | 
			
		||||
        &SPIRVDecompiler::HUnpack,
 | 
			
		||||
        &SPIRVDecompiler::HMergeF32,
 | 
			
		||||
        &SPIRVDecompiler::HMergeH0,
 | 
			
		||||
 | 
			
		||||
@ -57,7 +57,7 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
 | 
			
		||||
    case OpCode::Id::I2F_R:
 | 
			
		||||
    case OpCode::Id::I2F_C:
 | 
			
		||||
    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_MSG(instr.generates_cc,
 | 
			
		||||
                             "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);
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case OpCode::Id::F2F_R:
 | 
			
		||||
    case OpCode::Id::F2F_C:
 | 
			
		||||
    case OpCode::Id::F2F_IMM: {
 | 
			
		||||
        UNIMPLEMENTED_IF(instr.conversion.f2f.dst_size != Register::Size::Word);
 | 
			
		||||
        UNIMPLEMENTED_IF(instr.conversion.f2f.src_size != Register::Size::Word);
 | 
			
		||||
        UNIMPLEMENTED_IF(instr.conversion.dst_size == Register::Size::Long);
 | 
			
		||||
        UNIMPLEMENTED_IF(instr.conversion.src_size == Register::Size::Long);
 | 
			
		||||
        UNIMPLEMENTED_IF_MSG(instr.generates_cc,
 | 
			
		||||
                             "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 = [&]() {
 | 
			
		||||
@ -124,19 +134,24 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) {
 | 
			
		||||
            default:
 | 
			
		||||
                UNIMPLEMENTED_MSG("Unimplemented F2F rounding mode {}",
 | 
			
		||||
                                  static_cast<u32>(instr.conversion.f2f.rounding.Value()));
 | 
			
		||||
                return Immediate(0);
 | 
			
		||||
                return value;
 | 
			
		||||
            }
 | 
			
		||||
        }();
 | 
			
		||||
        value = GetSaturatedFloat(value, instr.alu.saturate_d);
 | 
			
		||||
 | 
			
		||||
        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);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case OpCode::Id::F2I_R:
 | 
			
		||||
    case OpCode::Id::F2I_C:
 | 
			
		||||
    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,
 | 
			
		||||
                             "Condition codes generation in F2I is not implemented");
 | 
			
		||||
        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 = [&]() {
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,8 @@ enum class OperationCode {
 | 
			
		||||
    FNegate,       /// (MetaArithmetic, float a) -> float
 | 
			
		||||
    FAbsolute,     /// (MetaArithmetic, float a) -> 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
 | 
			
		||||
    FMax,          /// (MetaArithmetic, float a, float b) -> float
 | 
			
		||||
    FCos,          /// (MetaArithmetic, float a) -> float
 | 
			
		||||
@ -83,17 +85,18 @@ enum class OperationCode {
 | 
			
		||||
    UBitfieldExtract, /// (MetaArithmetic, uint value, int offset, int offset) -> uint
 | 
			
		||||
    UBitCount,        /// (MetaArithmetic, uint) -> uint
 | 
			
		||||
 | 
			
		||||
    HAdd,      /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
 | 
			
		||||
    HMul,      /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
 | 
			
		||||
    HFma,      /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
 | 
			
		||||
    HAbsolute, /// (f16vec2 a) -> f16vec2
 | 
			
		||||
    HNegate,   /// (f16vec2 a, bool first, bool second) -> f16vec2
 | 
			
		||||
    HClamp,    /// (f16vec2 src, float min, float max) -> f16vec2
 | 
			
		||||
    HUnpack,   /// (Tegra::Shader::HalfType, T value) -> f16vec2
 | 
			
		||||
    HMergeF32, /// (f16vec2 src) -> float
 | 
			
		||||
    HMergeH0,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
 | 
			
		||||
    HMergeH1,  /// (f16vec2 dest, f16vec2 src) -> f16vec2
 | 
			
		||||
    HPack2,    /// (float a, float b) -> f16vec2
 | 
			
		||||
    HAdd,       /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
 | 
			
		||||
    HMul,       /// (MetaArithmetic, f16vec2 a, f16vec2 b) -> f16vec2
 | 
			
		||||
    HFma,       /// (MetaArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
 | 
			
		||||
    HAbsolute,  /// (f16vec2 a) -> f16vec2
 | 
			
		||||
    HNegate,    /// (f16vec2 a, bool first, bool second) -> f16vec2
 | 
			
		||||
    HClamp,     /// (f16vec2 src, float min, float max) -> f16vec2
 | 
			
		||||
    HCastFloat, /// (MetaArithmetic, float a) -> f16vec2
 | 
			
		||||
    HUnpack,    /// (Tegra::Shader::HalfType, T value) -> f16vec2
 | 
			
		||||
    HMergeF32,  /// (f16vec2 src) -> float
 | 
			
		||||
    HMergeH0,   /// (f16vec2 dest, f16vec2 src) -> f16vec2
 | 
			
		||||
    HMergeH1,   /// (f16vec2 dest, f16vec2 src) -> f16vec2
 | 
			
		||||
    HPack2,     /// (float a, float b) -> f16vec2
 | 
			
		||||
 | 
			
		||||
    LogicalAssign, /// (bool& dst, bool src) -> void
 | 
			
		||||
    LogicalAnd,    /// (bool a, bool b) -> bool
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user