Merge pull request #2409 from ReinUsesLisp/half-floats

shader_ir/decode: Miscellaneous fixes to half-float decompilation
This commit is contained in:
bunnei 2019-04-19 21:31:52 -04:00 committed by GitHub
commit 650d9b1044
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 181 additions and 136 deletions

View file

@ -119,14 +119,10 @@ std::string GetTopologyName(Tegra::Shader::OutputTopology topology) {
/// Returns true if an object has to be treated as precise
bool IsPrecise(Operation operand) {
const auto& meta = operand.GetMeta();
const auto& meta{operand.GetMeta()};
if (const auto arithmetic = std::get_if<MetaArithmetic>(&meta)) {
return arithmetic->precise;
}
if (const auto half_arithmetic = std::get_if<MetaHalfArithmetic>(&meta)) {
return half_arithmetic->precise;
}
return false;
}
@ -627,28 +623,7 @@ private:
}
std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) {
std::string value = VisitOperand(operation, operand_index);
switch (type) {
case Type::HalfFloat: {
const auto half_meta = std::get_if<MetaHalfArithmetic>(&operation.GetMeta());
if (!half_meta) {
value = "toHalf2(" + value + ')';
}
switch (half_meta->types.at(operand_index)) {
case Tegra::Shader::HalfType::H0_H1:
return "toHalf2(" + value + ')';
case Tegra::Shader::HalfType::F32:
return "vec2(" + value + ')';
case Tegra::Shader::HalfType::H0_H0:
return "vec2(toHalf2(" + value + ")[0])";
case Tegra::Shader::HalfType::H1_H1:
return "vec2(toHalf2(" + value + ")[1])";
}
}
default:
return CastOperand(value, type);
}
return CastOperand(VisitOperand(operation, operand_index), type);
}
std::string CastOperand(const std::string& value, Type type) const {
@ -662,9 +637,7 @@ private:
case Type::Uint:
return "ftou(" + value + ')';
case Type::HalfFloat:
// Can't be handled as a stand-alone value
UNREACHABLE();
return value;
return "toHalf2(" + value + ')';
}
UNREACHABLE();
return value;
@ -1083,13 +1056,40 @@ private:
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 HUnpack(Operation operation) {
const std::string operand{VisitOperand(operation, 0, Type::HalfFloat)};
const auto value = [&]() -> std::string {
switch (std::get<Tegra::Shader::HalfType>(operation.GetMeta())) {
case Tegra::Shader::HalfType::H0_H1:
return operand;
case Tegra::Shader::HalfType::F32:
return "vec2(fromHalf2(" + operand + "))";
case Tegra::Shader::HalfType::H0_H0:
return "vec2(" + operand + "[0])";
case Tegra::Shader::HalfType::H1_H1:
return "vec2(" + operand + "[1])";
}
UNREACHABLE();
return "0";
}();
return "fromHalf2(" + value + ')';
}
std::string HMergeF32(Operation operation) {
return "float(toHalf2(" + Visit(operation[0]) + ")[0])";
}
std::string HMergeH0(Operation operation) {
return "fromHalf2(vec2(toHalf2(" + Visit(operation[0]) + ")[1], toHalf2(" +
Visit(operation[1]) + ")[0]))";
return "fromHalf2(vec2(toHalf2(" + Visit(operation[1]) + ")[0], toHalf2(" +
Visit(operation[0]) + ")[1]))";
}
std::string HMergeH1(Operation operation) {
@ -1189,34 +1189,46 @@ private:
return GenerateUnary(operation, "any", Type::Bool, Type::Bool2);
}
template <bool with_nan>
std::string GenerateHalfComparison(Operation operation, std::string compare_op) {
std::string comparison{GenerateBinaryCall(operation, compare_op, Type::Bool2,
Type::HalfFloat, Type::HalfFloat)};
if constexpr (!with_nan) {
return comparison;
}
return "halfFloatNanComparison(" + comparison + ", " +
VisitOperand(operation, 0, Type::HalfFloat) + ", " +
VisitOperand(operation, 1, Type::HalfFloat) + ')';
}
template <bool with_nan>
std::string Logical2HLessThan(Operation operation) {
return GenerateBinaryCall(operation, "lessThan", Type::Bool2, Type::HalfFloat,
Type::HalfFloat);
return GenerateHalfComparison<with_nan>(operation, "lessThan");
}
template <bool with_nan>
std::string Logical2HEqual(Operation operation) {
return GenerateBinaryCall(operation, "equal", Type::Bool2, Type::HalfFloat,
Type::HalfFloat);
return GenerateHalfComparison<with_nan>(operation, "equal");
}
template <bool with_nan>
std::string Logical2HLessEqual(Operation operation) {
return GenerateBinaryCall(operation, "lessThanEqual", Type::Bool2, Type::HalfFloat,
Type::HalfFloat);
return GenerateHalfComparison<with_nan>(operation, "lessThanEqual");
}
template <bool with_nan>
std::string Logical2HGreaterThan(Operation operation) {
return GenerateBinaryCall(operation, "greaterThan", Type::Bool2, Type::HalfFloat,
Type::HalfFloat);
return GenerateHalfComparison<with_nan>(operation, "greaterThan");
}
template <bool with_nan>
std::string Logical2HNotEqual(Operation operation) {
return GenerateBinaryCall(operation, "notEqual", Type::Bool2, Type::HalfFloat,
Type::HalfFloat);
return GenerateHalfComparison<with_nan>(operation, "notEqual");
}
template <bool with_nan>
std::string Logical2HGreaterEqual(Operation operation) {
return GenerateBinaryCall(operation, "greaterThanEqual", Type::Bool2, Type::HalfFloat,
Type::HalfFloat);
return GenerateHalfComparison<with_nan>(operation, "greaterThanEqual");
}
std::string Texture(Operation operation) {
@ -1505,6 +1517,8 @@ private:
&GLSLDecompiler::Fma<Type::HalfFloat>,
&GLSLDecompiler::Absolute<Type::HalfFloat>,
&GLSLDecompiler::HNegate,
&GLSLDecompiler::HClamp,
&GLSLDecompiler::HUnpack,
&GLSLDecompiler::HMergeF32,
&GLSLDecompiler::HMergeH0,
&GLSLDecompiler::HMergeH1,
@ -1541,12 +1555,18 @@ private:
&GLSLDecompiler::LogicalNotEqual<Type::Uint>,
&GLSLDecompiler::LogicalGreaterEqual<Type::Uint>,
&GLSLDecompiler::Logical2HLessThan,
&GLSLDecompiler::Logical2HEqual,
&GLSLDecompiler::Logical2HLessEqual,
&GLSLDecompiler::Logical2HGreaterThan,
&GLSLDecompiler::Logical2HNotEqual,
&GLSLDecompiler::Logical2HGreaterEqual,
&GLSLDecompiler::Logical2HLessThan<false>,
&GLSLDecompiler::Logical2HEqual<false>,
&GLSLDecompiler::Logical2HLessEqual<false>,
&GLSLDecompiler::Logical2HGreaterThan<false>,
&GLSLDecompiler::Logical2HNotEqual<false>,
&GLSLDecompiler::Logical2HGreaterEqual<false>,
&GLSLDecompiler::Logical2HLessThan<true>,
&GLSLDecompiler::Logical2HEqual<true>,
&GLSLDecompiler::Logical2HLessEqual<true>,
&GLSLDecompiler::Logical2HGreaterThan<true>,
&GLSLDecompiler::Logical2HNotEqual<true>,
&GLSLDecompiler::Logical2HGreaterEqual<true>,
&GLSLDecompiler::Texture,
&GLSLDecompiler::TextureLod,
@ -1647,6 +1667,12 @@ std::string GetCommonDeclarations() {
"}\n\n"
"vec2 toHalf2(float value) {\n"
" return unpackHalf2x16(ftou(value));\n"
"}\n\n"
"bvec2 halfFloatNanComparison(bvec2 comparison, vec2 pair1, vec2 pair2) {\n"
" bvec2 is_nan1 = isnan(pair1);\n"
" bvec2 is_nan2 = isnan(pair2);\n"
" return bvec2(comparison.x || is_nan1.x || is_nan2.x, comparison.y || is_nan1.y || "
"is_nan2.y);\n"
"}\n";
}