|
@@ -3,12 +3,12 @@
|
|
|
// Refer to the license.txt file included.
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#include <map>
|
|
#include <map>
|
|
|
|
|
+#include <optional>
|
|
|
#include <set>
|
|
#include <set>
|
|
|
#include <string>
|
|
#include <string>
|
|
|
#include <string_view>
|
|
#include <string_view>
|
|
|
#include <unordered_set>
|
|
#include <unordered_set>
|
|
|
|
|
|
|
|
-#include <boost/optional.hpp>
|
|
|
|
|
#include <fmt/format.h>
|
|
#include <fmt/format.h>
|
|
|
|
|
|
|
|
#include "common/assert.h"
|
|
#include "common/assert.h"
|
|
@@ -144,7 +144,7 @@ private:
|
|
|
for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
|
|
for (u32 offset = begin; offset != end && offset != PROGRAM_END; ++offset) {
|
|
|
const Instruction instr = {program_code[offset]};
|
|
const Instruction instr = {program_code[offset]};
|
|
|
if (const auto opcode = OpCode::Decode(instr)) {
|
|
if (const auto opcode = OpCode::Decode(instr)) {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::EXIT: {
|
|
case OpCode::Id::EXIT: {
|
|
|
// The EXIT instruction can be predicated, which means that the shader can
|
|
// The EXIT instruction can be predicated, which means that the shader can
|
|
|
// conditionally end on this instruction. We have to consider the case where the
|
|
// conditionally end on this instruction. We have to consider the case where the
|
|
@@ -430,7 +430,7 @@ public:
|
|
|
*/
|
|
*/
|
|
|
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
|
|
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute,
|
|
|
const Tegra::Shader::IpaMode& input_mode,
|
|
const Tegra::Shader::IpaMode& input_mode,
|
|
|
- boost::optional<Register> vertex = {}) {
|
|
|
|
|
|
|
+ std::optional<Register> vertex = {}) {
|
|
|
const std::string dest = GetRegisterAsFloat(reg);
|
|
const std::string dest = GetRegisterAsFloat(reg);
|
|
|
const std::string src = GetInputAttribute(attribute, input_mode, vertex) + GetSwizzle(elem);
|
|
const std::string src = GetInputAttribute(attribute, input_mode, vertex) + GetSwizzle(elem);
|
|
|
shader.AddLine(dest + " = " + src + ';');
|
|
shader.AddLine(dest + " = " + src + ';');
|
|
@@ -807,10 +807,10 @@ private:
|
|
|
/// Generates code representing an input attribute register.
|
|
/// Generates code representing an input attribute register.
|
|
|
std::string GetInputAttribute(Attribute::Index attribute,
|
|
std::string GetInputAttribute(Attribute::Index attribute,
|
|
|
const Tegra::Shader::IpaMode& input_mode,
|
|
const Tegra::Shader::IpaMode& input_mode,
|
|
|
- boost::optional<Register> vertex = {}) {
|
|
|
|
|
|
|
+ std::optional<Register> vertex = {}) {
|
|
|
auto GeometryPass = [&](const std::string& name) {
|
|
auto GeometryPass = [&](const std::string& name) {
|
|
|
if (stage == Maxwell3D::Regs::ShaderStage::Geometry && vertex) {
|
|
if (stage == Maxwell3D::Regs::ShaderStage::Geometry && vertex) {
|
|
|
- return "gs_" + name + '[' + GetRegisterAsInteger(vertex.value(), 0, false) + ']';
|
|
|
|
|
|
|
+ return "gs_" + name + '[' + GetRegisterAsInteger(*vertex, 0, false) + ']';
|
|
|
}
|
|
}
|
|
|
return name;
|
|
return name;
|
|
|
};
|
|
};
|
|
@@ -1465,7 +1465,7 @@ private:
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
shader.AddLine(
|
|
shader.AddLine(
|
|
|
- fmt::format("// {}: {} (0x{:016x})", offset, opcode->GetName(), instr.value));
|
|
|
|
|
|
|
+ fmt::format("// {}: {} (0x{:016x})", offset, opcode->get().GetName(), instr.value));
|
|
|
|
|
|
|
|
using Tegra::Shader::Pred;
|
|
using Tegra::Shader::Pred;
|
|
|
ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
|
|
ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
|
|
@@ -1473,7 +1473,7 @@ private:
|
|
|
|
|
|
|
|
// Some instructions (like SSY) don't have a predicate field, they are always
|
|
// Some instructions (like SSY) don't have a predicate field, they are always
|
|
|
// unconditionally executed.
|
|
// unconditionally executed.
|
|
|
- bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->GetId());
|
|
|
|
|
|
|
+ bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->get().GetId());
|
|
|
|
|
|
|
|
if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
|
|
if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
|
|
|
shader.AddLine("if (" +
|
|
shader.AddLine("if (" +
|
|
@@ -1483,7 +1483,7 @@ private:
|
|
|
++shader.scope;
|
|
++shader.scope;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- switch (opcode->GetType()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetType()) {
|
|
|
case OpCode::Type::Arithmetic: {
|
|
case OpCode::Type::Arithmetic: {
|
|
|
std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
|
std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
|
|
@@ -1500,7 +1500,7 @@ private:
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::MOV_C:
|
|
case OpCode::Id::MOV_C:
|
|
|
case OpCode::Id::MOV_R: {
|
|
case OpCode::Id::MOV_R: {
|
|
|
// MOV does not have neither 'abs' nor 'neg' bits.
|
|
// MOV does not have neither 'abs' nor 'neg' bits.
|
|
@@ -1600,14 +1600,15 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {}",
|
|
|
|
|
+ opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case OpCode::Type::ArithmeticImmediate: {
|
|
case OpCode::Type::ArithmeticImmediate: {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::MOV32_IMM: {
|
|
case OpCode::Id::MOV32_IMM: {
|
|
|
regs.SetRegisterToFloat(instr.gpr0, 0, GetImmediate32(instr), 1, 1);
|
|
regs.SetRegisterToFloat(instr.gpr0, 0, GetImmediate32(instr), 1, 1);
|
|
|
break;
|
|
break;
|
|
@@ -1651,7 +1652,7 @@ private:
|
|
|
std::string op_a = instr.bfe.negate_a ? "-" : "";
|
|
std::string op_a = instr.bfe.negate_a ? "-" : "";
|
|
|
op_a += regs.GetRegisterAsInteger(instr.gpr8);
|
|
op_a += regs.GetRegisterAsInteger(instr.gpr8);
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::BFE_IMM: {
|
|
case OpCode::Id::BFE_IMM: {
|
|
|
std::string inner_shift =
|
|
std::string inner_shift =
|
|
|
'(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')';
|
|
'(' + op_a + " << " + std::to_string(instr.bfe.GetLeftShiftValue()) + ')';
|
|
@@ -1663,7 +1664,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled BFE instruction: {}", opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1685,7 +1686,7 @@ private:
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::SHR_C:
|
|
case OpCode::Id::SHR_C:
|
|
|
case OpCode::Id::SHR_R:
|
|
case OpCode::Id::SHR_R:
|
|
|
case OpCode::Id::SHR_IMM: {
|
|
case OpCode::Id::SHR_IMM: {
|
|
@@ -1705,7 +1706,7 @@ private:
|
|
|
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1);
|
|
regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1);
|
|
|
break;
|
|
break;
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled shift instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled shift instruction: {}", opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1715,7 +1716,7 @@ private:
|
|
|
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
|
|
std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
|
|
|
std::string op_b = std::to_string(instr.alu.imm20_32.Value());
|
|
std::string op_b = std::to_string(instr.alu.imm20_32.Value());
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::IADD32I:
|
|
case OpCode::Id::IADD32I:
|
|
|
if (instr.iadd32i.negate_a)
|
|
if (instr.iadd32i.negate_a)
|
|
|
op_a = "-(" + op_a + ')';
|
|
op_a = "-(" + op_a + ')';
|
|
@@ -1737,7 +1738,7 @@ private:
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}",
|
|
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticIntegerImmediate instruction: {}",
|
|
|
- opcode->GetName());
|
|
|
|
|
|
|
+ opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1757,7 +1758,7 @@ private:
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::IADD_C:
|
|
case OpCode::Id::IADD_C:
|
|
|
case OpCode::Id::IADD_R:
|
|
case OpCode::Id::IADD_R:
|
|
|
case OpCode::Id::IADD_IMM: {
|
|
case OpCode::Id::IADD_IMM: {
|
|
@@ -1793,7 +1794,7 @@ private:
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- if (opcode->GetId() == OpCode::Id::IADD3_R) {
|
|
|
|
|
|
|
+ if (opcode->get().GetId() == OpCode::Id::IADD3_R) {
|
|
|
apply_height(instr.iadd3.height_a, op_a);
|
|
apply_height(instr.iadd3.height_a, op_a);
|
|
|
apply_height(instr.iadd3.height_b, op_b);
|
|
apply_height(instr.iadd3.height_b, op_b);
|
|
|
apply_height(instr.iadd3.height_c, op_c);
|
|
apply_height(instr.iadd3.height_c, op_c);
|
|
@@ -1809,7 +1810,7 @@ private:
|
|
|
op_c = "-(" + op_c + ')';
|
|
op_c = "-(" + op_c + ')';
|
|
|
|
|
|
|
|
std::string result;
|
|
std::string result;
|
|
|
- if (opcode->GetId() == OpCode::Id::IADD3_R) {
|
|
|
|
|
|
|
+ if (opcode->get().GetId() == OpCode::Id::IADD3_R) {
|
|
|
switch (instr.iadd3.mode) {
|
|
switch (instr.iadd3.mode) {
|
|
|
case Tegra::Shader::IAdd3Mode::RightShift:
|
|
case Tegra::Shader::IAdd3Mode::RightShift:
|
|
|
// TODO(tech4me): According to
|
|
// TODO(tech4me): According to
|
|
@@ -1884,7 +1885,7 @@ private:
|
|
|
const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
|
|
const std::string op_c = regs.GetRegisterAsInteger(instr.gpr39);
|
|
|
std::string lut;
|
|
std::string lut;
|
|
|
|
|
|
|
|
- if (opcode->GetId() == OpCode::Id::LOP3_R) {
|
|
|
|
|
|
|
+ if (opcode->get().GetId() == OpCode::Id::LOP3_R) {
|
|
|
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')';
|
|
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut28()) + ')';
|
|
|
} else {
|
|
} else {
|
|
|
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut48()) + ')';
|
|
lut = '(' + std::to_string(instr.alu.lop3.GetImmLut48()) + ')';
|
|
@@ -1914,7 +1915,7 @@ private:
|
|
|
case OpCode::Id::LEA_HI: {
|
|
case OpCode::Id::LEA_HI: {
|
|
|
std::string op_c;
|
|
std::string op_c;
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::LEA_R2: {
|
|
case OpCode::Id::LEA_R2: {
|
|
|
op_a = regs.GetRegisterAsInteger(instr.gpr20);
|
|
op_a = regs.GetRegisterAsInteger(instr.gpr20);
|
|
|
op_b = regs.GetRegisterAsInteger(instr.gpr39);
|
|
op_b = regs.GetRegisterAsInteger(instr.gpr39);
|
|
@@ -1959,7 +1960,8 @@ private:
|
|
|
op_b = regs.GetRegisterAsInteger(instr.gpr8);
|
|
op_b = regs.GetRegisterAsInteger(instr.gpr8);
|
|
|
op_a = std::to_string(instr.lea.imm.entry_a);
|
|
op_a = std::to_string(instr.lea.imm.entry_a);
|
|
|
op_c = std::to_string(instr.lea.imm.entry_b);
|
|
op_c = std::to_string(instr.lea.imm.entry_b);
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled LEA subinstruction: {}",
|
|
|
|
|
+ opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1974,7 +1976,7 @@ private:
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
|
|
LOG_CRITICAL(HW_GPU, "Unhandled ArithmeticInteger instruction: {}",
|
|
|
- opcode->GetName());
|
|
|
|
|
|
|
+ opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -1982,20 +1984,21 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case OpCode::Type::ArithmeticHalf: {
|
|
case OpCode::Type::ArithmeticHalf: {
|
|
|
- if (opcode->GetId() == OpCode::Id::HADD2_C || opcode->GetId() == OpCode::Id::HADD2_R) {
|
|
|
|
|
|
|
+ if (opcode->get().GetId() == OpCode::Id::HADD2_C ||
|
|
|
|
|
+ opcode->get().GetId() == OpCode::Id::HADD2_R) {
|
|
|
ASSERT_MSG(instr.alu_half.ftz == 0, "Unimplemented");
|
|
ASSERT_MSG(instr.alu_half.ftz == 0, "Unimplemented");
|
|
|
}
|
|
}
|
|
|
const bool negate_a =
|
|
const bool negate_a =
|
|
|
- opcode->GetId() != OpCode::Id::HMUL2_R && instr.alu_half.negate_a != 0;
|
|
|
|
|
|
|
+ opcode->get().GetId() != OpCode::Id::HMUL2_R && instr.alu_half.negate_a != 0;
|
|
|
const bool negate_b =
|
|
const bool negate_b =
|
|
|
- opcode->GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0;
|
|
|
|
|
|
|
+ opcode->get().GetId() != OpCode::Id::HMUL2_C && instr.alu_half.negate_b != 0;
|
|
|
|
|
|
|
|
const std::string op_a =
|
|
const std::string op_a =
|
|
|
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.alu_half.type_a,
|
|
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.alu_half.type_a,
|
|
|
instr.alu_half.abs_a != 0, negate_a);
|
|
instr.alu_half.abs_a != 0, negate_a);
|
|
|
|
|
|
|
|
std::string op_b;
|
|
std::string op_b;
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::HADD2_C:
|
|
case OpCode::Id::HADD2_C:
|
|
|
case OpCode::Id::HMUL2_C:
|
|
case OpCode::Id::HMUL2_C:
|
|
|
op_b = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
op_b = regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
@@ -2013,7 +2016,7 @@ private:
|
|
|
op_b = GetHalfFloat(op_b, instr.alu_half.type_b, instr.alu_half.abs_b != 0, negate_b);
|
|
op_b = GetHalfFloat(op_b, instr.alu_half.type_b, instr.alu_half.abs_b != 0, negate_b);
|
|
|
|
|
|
|
|
const std::string result = [&]() {
|
|
const std::string result = [&]() {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::HADD2_C:
|
|
case OpCode::Id::HADD2_C:
|
|
|
case OpCode::Id::HADD2_R:
|
|
case OpCode::Id::HADD2_R:
|
|
|
return '(' + op_a + " + " + op_b + ')';
|
|
return '(' + op_a + " + " + op_b + ')';
|
|
@@ -2021,7 +2024,8 @@ private:
|
|
|
case OpCode::Id::HMUL2_R:
|
|
case OpCode::Id::HMUL2_R:
|
|
|
return '(' + op_a + " * " + op_b + ')';
|
|
return '(' + op_a + " * " + op_b + ')';
|
|
|
default:
|
|
default:
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled half float instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled half float instruction: {}",
|
|
|
|
|
+ opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
return std::string("0");
|
|
return std::string("0");
|
|
|
}
|
|
}
|
|
@@ -2032,7 +2036,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case OpCode::Type::ArithmeticHalfImmediate: {
|
|
case OpCode::Type::ArithmeticHalfImmediate: {
|
|
|
- if (opcode->GetId() == OpCode::Id::HADD2_IMM) {
|
|
|
|
|
|
|
+ if (opcode->get().GetId() == OpCode::Id::HADD2_IMM) {
|
|
|
ASSERT_MSG(instr.alu_half_imm.ftz == 0, "Unimplemented");
|
|
ASSERT_MSG(instr.alu_half_imm.ftz == 0, "Unimplemented");
|
|
|
} else {
|
|
} else {
|
|
|
ASSERT_MSG(instr.alu_half_imm.precision == Tegra::Shader::HalfPrecision::None,
|
|
ASSERT_MSG(instr.alu_half_imm.precision == Tegra::Shader::HalfPrecision::None,
|
|
@@ -2046,7 +2050,7 @@ private:
|
|
|
const std::string op_b = UnpackHalfImmediate(instr, true);
|
|
const std::string op_b = UnpackHalfImmediate(instr, true);
|
|
|
|
|
|
|
|
const std::string result = [&]() {
|
|
const std::string result = [&]() {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::HADD2_IMM:
|
|
case OpCode::Id::HADD2_IMM:
|
|
|
return op_a + " + " + op_b;
|
|
return op_a + " + " + op_b;
|
|
|
case OpCode::Id::HMUL2_IMM:
|
|
case OpCode::Id::HMUL2_IMM:
|
|
@@ -2072,7 +2076,7 @@ private:
|
|
|
ASSERT_MSG(instr.ffma.tab5980_1 == 0, "FFMA tab5980_1({}) not implemented",
|
|
ASSERT_MSG(instr.ffma.tab5980_1 == 0, "FFMA tab5980_1({}) not implemented",
|
|
|
instr.ffma.tab5980_1.Value());
|
|
instr.ffma.tab5980_1.Value());
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::FFMA_CR: {
|
|
case OpCode::Id::FFMA_CR: {
|
|
|
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
|
GLSLRegister::Type::Float);
|
|
GLSLRegister::Type::Float);
|
|
@@ -2096,7 +2100,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {}", opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -2107,14 +2111,14 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case OpCode::Type::Hfma2: {
|
|
case OpCode::Type::Hfma2: {
|
|
|
- if (opcode->GetId() == OpCode::Id::HFMA2_RR) {
|
|
|
|
|
|
|
+ if (opcode->get().GetId() == OpCode::Id::HFMA2_RR) {
|
|
|
ASSERT_MSG(instr.hfma2.rr.precision == Tegra::Shader::HalfPrecision::None,
|
|
ASSERT_MSG(instr.hfma2.rr.precision == Tegra::Shader::HalfPrecision::None,
|
|
|
"Unimplemented");
|
|
"Unimplemented");
|
|
|
} else {
|
|
} else {
|
|
|
ASSERT_MSG(instr.hfma2.precision == Tegra::Shader::HalfPrecision::None,
|
|
ASSERT_MSG(instr.hfma2.precision == Tegra::Shader::HalfPrecision::None,
|
|
|
"Unimplemented");
|
|
"Unimplemented");
|
|
|
}
|
|
}
|
|
|
- const bool saturate = opcode->GetId() == OpCode::Id::HFMA2_RR
|
|
|
|
|
|
|
+ const bool saturate = opcode->get().GetId() == OpCode::Id::HFMA2_RR
|
|
|
? instr.hfma2.rr.saturate != 0
|
|
? instr.hfma2.rr.saturate != 0
|
|
|
: instr.hfma2.saturate != 0;
|
|
: instr.hfma2.saturate != 0;
|
|
|
|
|
|
|
@@ -2122,7 +2126,7 @@ private:
|
|
|
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hfma2.type_a);
|
|
GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr8, 0, false), instr.hfma2.type_a);
|
|
|
std::string op_b, op_c;
|
|
std::string op_b, op_c;
|
|
|
|
|
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::HFMA2_CR:
|
|
case OpCode::Id::HFMA2_CR:
|
|
|
op_b = GetHalfFloat(regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
op_b = GetHalfFloat(regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
|
GLSLRegister::Type::UnsignedInteger),
|
|
GLSLRegister::Type::UnsignedInteger),
|
|
@@ -2160,7 +2164,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case OpCode::Type::Conversion: {
|
|
case OpCode::Type::Conversion: {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::I2I_R: {
|
|
case OpCode::Id::I2I_R: {
|
|
|
ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
|
|
ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
|
|
|
|
|
|
|
@@ -2298,14 +2302,15 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}",
|
|
|
|
|
+ opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case OpCode::Type::Memory: {
|
|
case OpCode::Type::Memory: {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::LD_A: {
|
|
case OpCode::Id::LD_A: {
|
|
|
// Note: Shouldn't this be interp mode flat? As in no interpolation made.
|
|
// Note: Shouldn't this be interp mode flat? As in no interpolation made.
|
|
|
ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex,
|
|
ASSERT_MSG(instr.gpr8.Value() == Register::ZeroIndex,
|
|
@@ -2949,7 +2954,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {}", opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -3043,7 +3048,7 @@ private:
|
|
|
instr.hsetp2.abs_a, instr.hsetp2.negate_a);
|
|
instr.hsetp2.abs_a, instr.hsetp2.negate_a);
|
|
|
|
|
|
|
|
const std::string op_b = [&]() {
|
|
const std::string op_b = [&]() {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::HSETP2_R:
|
|
case OpCode::Id::HSETP2_R:
|
|
|
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
|
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
|
|
instr.hsetp2.type_b, instr.hsetp2.abs_a,
|
|
instr.hsetp2.type_b, instr.hsetp2.abs_a,
|
|
@@ -3105,7 +3110,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case OpCode::Type::PredicateSetPredicate: {
|
|
case OpCode::Type::PredicateSetPredicate: {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::PSETP: {
|
|
case OpCode::Id::PSETP: {
|
|
|
const std::string op_a =
|
|
const std::string op_a =
|
|
|
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
|
|
GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
|
|
@@ -3151,7 +3156,8 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}",
|
|
|
|
|
+ opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -3239,7 +3245,7 @@ private:
|
|
|
instr.hset2.abs_a != 0, instr.hset2.negate_a != 0);
|
|
instr.hset2.abs_a != 0, instr.hset2.negate_a != 0);
|
|
|
|
|
|
|
|
const std::string op_b = [&]() {
|
|
const std::string op_b = [&]() {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::HSET2_R:
|
|
case OpCode::Id::HSET2_R:
|
|
|
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
|
return GetHalfFloat(regs.GetRegisterAsInteger(instr.gpr20, 0, false),
|
|
|
instr.hset2.type_b, instr.hset2.abs_b != 0,
|
|
instr.hset2.type_b, instr.hset2.abs_b != 0,
|
|
@@ -3288,7 +3294,7 @@ private:
|
|
|
const bool is_signed{instr.xmad.sign_a == 1};
|
|
const bool is_signed{instr.xmad.sign_a == 1};
|
|
|
|
|
|
|
|
bool is_merge{};
|
|
bool is_merge{};
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::XMAD_CR: {
|
|
case OpCode::Id::XMAD_CR: {
|
|
|
is_merge = instr.xmad.merge_56;
|
|
is_merge = instr.xmad.merge_56;
|
|
|
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset,
|
|
@@ -3317,7 +3323,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -3369,7 +3375,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- switch (opcode->GetId()) {
|
|
|
|
|
|
|
+ switch (opcode->get().GetId()) {
|
|
|
case OpCode::Id::EXIT: {
|
|
case OpCode::Id::EXIT: {
|
|
|
if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
|
|
if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
|
|
|
EmitFragmentOutputsWrite();
|
|
EmitFragmentOutputsWrite();
|
|
@@ -3564,7 +3570,7 @@ private:
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
default: {
|
|
default: {
|
|
|
- LOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->GetName());
|
|
|
|
|
|
|
+ LOG_CRITICAL(HW_GPU, "Unhandled instruction: {}", opcode->get().GetName());
|
|
|
UNREACHABLE();
|
|
UNREACHABLE();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -3705,9 +3711,9 @@ std::string GetCommonDeclarations() {
|
|
|
RasterizerOpenGL::MaxConstbufferSize / sizeof(GLvec4));
|
|
RasterizerOpenGL::MaxConstbufferSize / sizeof(GLvec4));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
|
|
|
|
|
- Maxwell3D::Regs::ShaderStage stage,
|
|
|
|
|
- const std::string& suffix) {
|
|
|
|
|
|
|
+std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u32 main_offset,
|
|
|
|
|
+ Maxwell3D::Regs::ShaderStage stage,
|
|
|
|
|
+ const std::string& suffix) {
|
|
|
try {
|
|
try {
|
|
|
const auto subroutines =
|
|
const auto subroutines =
|
|
|
ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
|
|
ControlFlowAnalyzer(program_code, main_offset, suffix).GetSubroutines();
|
|
@@ -3716,7 +3722,7 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code,
|
|
|
} catch (const DecompileFail& exception) {
|
|
} catch (const DecompileFail& exception) {
|
|
|
LOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
|
LOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
|
|
}
|
|
}
|
|
|
- return boost::none;
|
|
|
|
|
|
|
+ return {};
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} // namespace OpenGL::GLShader::Decompiler
|
|
} // namespace OpenGL::GLShader::Decompiler
|