mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-27 01:02:48 +01:00
shader_ir/decode: Implement half float saturation
This commit is contained in:
parent
90cbf89303
commit
64613db605
5 changed files with 31 additions and 8 deletions
|
@ -617,13 +617,11 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
|
std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
|
||||||
std::string value = VisitOperand(operation, operand_index);
|
const std::string value = VisitOperand(operation, operand_index);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::HalfFloat: {
|
case Type::HalfFloat: {
|
||||||
const auto half_meta = std::get_if<MetaHalfArithmetic>(&operation.GetMeta());
|
const auto half_meta = std::get_if<MetaHalfArithmetic>(&operation.GetMeta());
|
||||||
if (!half_meta) {
|
ASSERT(half_meta);
|
||||||
value = "toHalf2(" + value + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (half_meta->types.at(operand_index)) {
|
switch (half_meta->types.at(operand_index)) {
|
||||||
case Tegra::Shader::HalfType::H0_H1:
|
case Tegra::Shader::HalfType::H0_H1:
|
||||||
|
@ -1067,6 +1065,14 @@ private:
|
||||||
return BitwiseCastResult(value, Type::HalfFloat);
|
return BitwiseCastResult(value, Type::HalfFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string HClamp(Operation operation) {
|
||||||
|
const std::string value = VisitOperand(operation, 0, Type::HalfFloat);
|
||||||
|
const std::string min = VisitOperand(operation, 1, Type::Float);
|
||||||
|
const std::string max = VisitOperand(operation, 2, Type::Float);
|
||||||
|
const std::string clamped = "clamp(" + value + ", vec2(" + min + "), vec2(" + max + "))";
|
||||||
|
return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat));
|
||||||
|
}
|
||||||
|
|
||||||
std::string HMergeF32(Operation operation) {
|
std::string HMergeF32(Operation operation) {
|
||||||
return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
|
return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
|
||||||
}
|
}
|
||||||
|
@ -1501,6 +1507,7 @@ private:
|
||||||
&GLSLDecompiler::Fma<Type::HalfFloat>,
|
&GLSLDecompiler::Fma<Type::HalfFloat>,
|
||||||
&GLSLDecompiler::Absolute<Type::HalfFloat>,
|
&GLSLDecompiler::Absolute<Type::HalfFloat>,
|
||||||
&GLSLDecompiler::HNegate,
|
&GLSLDecompiler::HNegate,
|
||||||
|
&GLSLDecompiler::HClamp,
|
||||||
&GLSLDecompiler::HMergeF32,
|
&GLSLDecompiler::HMergeF32,
|
||||||
&GLSLDecompiler::HMergeH0,
|
&GLSLDecompiler::HMergeH0,
|
||||||
&GLSLDecompiler::HMergeH1,
|
&GLSLDecompiler::HMergeH1,
|
||||||
|
|
|
@ -744,6 +744,11 @@ private:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Id HClamp(Operation operation) {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Id HMergeF32(Operation operation) {
|
Id HMergeF32(Operation operation) {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
return {};
|
return {};
|
||||||
|
@ -1216,6 +1221,7 @@ private:
|
||||||
&SPIRVDecompiler::Ternary<&Module::OpFma, Type::HalfFloat>,
|
&SPIRVDecompiler::Ternary<&Module::OpFma, Type::HalfFloat>,
|
||||||
&SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>,
|
&SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>,
|
||||||
&SPIRVDecompiler::HNegate,
|
&SPIRVDecompiler::HNegate,
|
||||||
|
&SPIRVDecompiler::HClamp,
|
||||||
&SPIRVDecompiler::HMergeF32,
|
&SPIRVDecompiler::HMergeF32,
|
||||||
&SPIRVDecompiler::HMergeH0,
|
&SPIRVDecompiler::HMergeH0,
|
||||||
&SPIRVDecompiler::HMergeH1,
|
&SPIRVDecompiler::HMergeH1,
|
||||||
|
|
|
@ -23,8 +23,6 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
|
||||||
} else {
|
} else {
|
||||||
UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None);
|
UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None);
|
||||||
}
|
}
|
||||||
UNIMPLEMENTED_IF_MSG(instr.alu_half_imm.saturate != 0,
|
|
||||||
"Half float immediate saturation not implemented");
|
|
||||||
|
|
||||||
Node op_a = GetRegister(instr.gpr8);
|
Node op_a = GetRegister(instr.gpr8);
|
||||||
op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a);
|
op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a);
|
||||||
|
@ -43,10 +41,10 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) {
|
||||||
return Immediate(0);
|
return Immediate(0);
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
value = GetSaturatedHalfFloat(value, instr.alu_half_imm.saturate);
|
||||||
value = HalfMerge(GetRegister(instr.gpr0), value, instr.alu_half_imm.merge);
|
value = HalfMerge(GetRegister(instr.gpr0), value, instr.alu_half_imm.merge);
|
||||||
|
|
||||||
SetRegister(bb, instr.gpr0, value);
|
SetRegister(bb, instr.gpr0, value);
|
||||||
|
|
||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,15 @@ Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node ShaderIR::GetSaturatedHalfFloat(Node value, bool saturate) {
|
||||||
|
if (!saturate) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
const Node positive_zero = Immediate(std::copysignf(0, 1));
|
||||||
|
const Node positive_one = Immediate(1.0f);
|
||||||
|
return Operation(OperationCode::HClamp, HALF_NO_PRECISE, value, positive_zero, positive_one);
|
||||||
|
}
|
||||||
|
|
||||||
Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
|
Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) {
|
||||||
const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
|
const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = {
|
||||||
{PredCondition::LessThan, OperationCode::LogicalFLessThan},
|
{PredCondition::LessThan, OperationCode::LogicalFLessThan},
|
||||||
|
|
|
@ -114,6 +114,7 @@ enum class OperationCode {
|
||||||
HFma, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2
|
HFma, /// (MetaHalfArithmetic, 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
|
||||||
HMergeF32, /// (f16vec2 src) -> float
|
HMergeF32, /// (f16vec2 src) -> float
|
||||||
HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
||||||
HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2
|
||||||
|
@ -716,6 +717,8 @@ private:
|
||||||
Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge);
|
Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge);
|
||||||
/// Conditionally absolute/negated half float pair. Absolute is applied first
|
/// Conditionally absolute/negated half float pair. Absolute is applied first
|
||||||
Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate);
|
Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate);
|
||||||
|
/// Conditionally saturates a half float pair
|
||||||
|
Node GetSaturatedHalfFloat(Node value, bool saturate = true);
|
||||||
|
|
||||||
/// Returns a predicate comparing two floats
|
/// Returns a predicate comparing two floats
|
||||||
Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b);
|
Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b);
|
||||||
|
|
Loading…
Reference in a new issue