From 15a0e1481d9a1efb3e3aa61cbaf2fa1ba0392d71 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 19:09:21 -0300 Subject: shader_ir: Initial implementation --- src/video_core/shader/decode/arithmetic.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/video_core/shader/decode/arithmetic.cpp (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp new file mode 100644 index 000000000..9242a7389 --- /dev/null +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -0,0 +1,24 @@ +// Copyright 2018 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/common_types.h" +#include "video_core/engines/shader_bytecode.h" +#include "video_core/shader/shader_ir.h" + +namespace VideoCommon::Shader { + +using Tegra::Shader::Instruction; +using Tegra::Shader::OpCode; + +u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { + const Instruction instr = {program_code[pc]}; + const auto opcode = OpCode::Decode(instr); + + UNIMPLEMENTED(); + + return pc; +} + +} // namespace VideoCommon::Shader \ No newline at end of file -- cgit v1.2.3 From 4c70d5b8eb68a61f5504a05dd597ecb2b04441b5 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:53:50 -0300 Subject: shader_decode: Implement MOV_C and MOV_R --- src/video_core/shader/decode/arithmetic.cpp | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index 9242a7389..c297f729e 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -11,12 +11,34 @@ namespace VideoCommon::Shader { using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; +using Tegra::Shader::SubOp; u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { const Instruction instr = {program_code[pc]}; const auto opcode = OpCode::Decode(instr); - UNIMPLEMENTED(); + Node op_a = GetRegister(instr.gpr8); + + Node op_b = [&]() -> Node { + if (instr.is_b_imm) { + return GetImmediate19(instr); + } else if (instr.is_b_gpr) { + return GetRegister(instr.gpr20); + } else { + return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset); + } + }(); + + switch (opcode->get().GetId()) { + case OpCode::Id::MOV_C: + case OpCode::Id::MOV_R: { + // MOV does not have neither 'abs' nor 'neg' bits. + SetRegister(bb, instr.gpr0, op_b); + break; + } + default: + UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName()); + } return pc; } -- cgit v1.2.3 From 7c192ec43fb6a08baea5d55aa47fcf3fa98d4343 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:54:47 -0300 Subject: shader_decode: Implement FMUL_C, FMUL_R and FMUL_IMM --- src/video_core/shader/decode/arithmetic.cpp | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index c297f729e..78bca79e3 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -36,6 +36,48 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, op_b); break; } + case OpCode::Id::FMUL_C: + case OpCode::Id::FMUL_R: + case OpCode::Id::FMUL_IMM: { + // FMUL does not have 'abs' bits and only the second operand has a 'neg' bit. + UNIMPLEMENTED_IF_MSG(instr.fmul.tab5cb8_2 != 0, "FMUL tab5cb8_2({}) is not implemented", + instr.fmul.tab5cb8_2.Value()); + UNIMPLEMENTED_IF_MSG( + instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented", + instr.fmul.tab5c68_0.Value()); // SMO typical sends 1 here which seems to be the default + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in FMUL is not implemented"); + + op_b = GetOperandAbsNegFloat(op_b, false, instr.fmul.negate_b); + + // TODO(Rodrigo): Should precise be used when there's a postfactor? + Node value = Operation(OperationCode::FMul, PRECISE, op_a, op_b); + + if (instr.fmul.postfactor != 0) { + auto postfactor = static_cast(instr.fmul.postfactor); + + // Postfactor encoded as 3-bit 1's complement in instruction, interpreted with below + // logic. + if (postfactor >= 4) { + postfactor = 7 - postfactor; + } else { + postfactor = 0 - postfactor; + } + + if (postfactor > 0) { + value = Operation(OperationCode::FMul, NO_PRECISE, value, + Immediate(static_cast(1 << postfactor))); + } else { + value = Operation(OperationCode::FDiv, NO_PRECISE, value, + Immediate(static_cast(1 << -postfactor))); + } + } + + value = GetSaturatedFloat(value, instr.alu.saturate_d); + + SetRegister(bb, instr.gpr0, value); + break; + } default: UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From 4ccaa1402d376af14d8527c0a0bcc77be007bd3c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:55:19 -0300 Subject: shader_decode: Implement FADD_C, FADD_R and FADD_IMM --- src/video_core/shader/decode/arithmetic.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index 78bca79e3..d196d94b5 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -78,6 +78,21 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, value); break; } + case OpCode::Id::FADD_C: + case OpCode::Id::FADD_R: + case OpCode::Id::FADD_IMM: { + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in FADD is not implemented"); + + op_a = GetOperandAbsNegFloat(op_a, instr.alu.abs_a, instr.alu.negate_a); + op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b); + + Node value = Operation(OperationCode::FAdd, PRECISE, op_a, op_b); + value = GetSaturatedFloat(value, instr.alu.saturate_d); + + SetRegister(bb, instr.gpr0, value); + break; + } default: UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From 964ddeeb90b655d8b5558002db7c780c0394263c Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:56:21 -0300 Subject: shader_decode: Implement MUFU --- src/video_core/shader/decode/arithmetic.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index d196d94b5..fb688c324 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -93,6 +93,35 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, value); break; } + case OpCode::Id::MUFU: { + op_a = GetOperandAbsNegFloat(op_a, instr.alu.abs_a, instr.alu.negate_a); + + Node value = [&]() { + switch (instr.sub_op) { + case SubOp::Cos: + return Operation(OperationCode::FCos, PRECISE, op_a); + case SubOp::Sin: + return Operation(OperationCode::FSin, PRECISE, op_a); + case SubOp::Ex2: + return Operation(OperationCode::FExp2, PRECISE, op_a); + case SubOp::Lg2: + return Operation(OperationCode::FLog2, PRECISE, op_a); + case SubOp::Rcp: + return Operation(OperationCode::FDiv, PRECISE, Immediate(1.0f), op_a); + case SubOp::Rsq: + return Operation(OperationCode::FInverseSqrt, PRECISE, op_a); + case SubOp::Sqrt: + return Operation(OperationCode::FSqrt, PRECISE, op_a); + default: + UNIMPLEMENTED_MSG("Unhandled MUFU sub op={0:x}", + static_cast(instr.sub_op.Value())); + } + }(); + value = GetSaturatedFloat(value, instr.alu.saturate_d); + + SetRegister(bb, instr.gpr0, value); + break; + } default: UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From 5e6a0a08c14df8e1993f4f72b1bbfd388a5ea48e Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:56:45 -0300 Subject: shader_decode: Implement FMNMX_C, FMNMX_R and FMNMX_IMM --- src/video_core/shader/decode/arithmetic.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index fb688c324..0b6654397 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -122,6 +122,24 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { SetRegister(bb, instr.gpr0, value); break; } + case OpCode::Id::FMNMX_C: + case OpCode::Id::FMNMX_R: + case OpCode::Id::FMNMX_IMM: { + UNIMPLEMENTED_IF_MSG(instr.generates_cc, + "Condition codes generation in FMNMX is not implemented"); + + op_a = GetOperandAbsNegFloat(op_a, instr.alu.abs_a, instr.alu.negate_a); + op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b); + + const Node condition = GetPredicate(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0); + + const Node min = Operation(OperationCode::FMin, NO_PRECISE, op_a, op_b); + const Node max = Operation(OperationCode::FMax, NO_PRECISE, op_a, op_b); + + SetRegister(bb, instr.gpr0, + Operation(OperationCode::Select, NO_PRECISE, condition, min, max)); + break; + } default: UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From 06cb910c6d9b0be664db4305f90974198f84ae98 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 20 Dec 2018 23:57:09 -0300 Subject: shader_decode: Stub RRO_C, RRO_R and RRO_IMM --- src/video_core/shader/decode/arithmetic.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index 0b6654397..9f8c27b3e 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -140,6 +140,15 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { Operation(OperationCode::Select, NO_PRECISE, condition, min, max)); break; } + case OpCode::Id::RRO_C: + case OpCode::Id::RRO_R: + case OpCode::Id::RRO_IMM: { + // Currently RRO is only implemented as a register move. + op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b); + SetRegister(bb, instr.gpr0, op_b); + LOG_WARNING(HW_GPU, "RRO instruction is incomplete"); + break; + } default: UNIMPLEMENTED_MSG("Unhandled arithmetic instruction: {}", opcode->get().GetName()); } -- cgit v1.2.3 From fc46ecddb3bca4861babbf610cd64ab9fdc1bb08 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 21 Dec 2018 18:47:22 -0300 Subject: video_core: Return safe values after an assert hits --- src/video_core/shader/decode/arithmetic.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index 9f8c27b3e..ef846bd9a 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -115,6 +115,7 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { default: UNIMPLEMENTED_MSG("Unhandled MUFU sub op={0:x}", static_cast(instr.sub_op.Value())); + return Immediate(0); } }(); value = GetSaturatedFloat(value, instr.alu.saturate_d); -- cgit v1.2.3 From 2d6c064e66bac4cb871aa26a12066441a8852008 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 27 Dec 2018 16:50:36 -0300 Subject: shader_decode: Improve zero flag implementation --- src/video_core/shader/decode/arithmetic.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index ef846bd9a..926abcc8e 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -45,8 +45,6 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { UNIMPLEMENTED_IF_MSG( instr.fmul.tab5c68_0 != 1, "FMUL tab5cb8_0({}) is not implemented", instr.fmul.tab5c68_0.Value()); // SMO typical sends 1 here which seems to be the default - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in FMUL is not implemented"); op_b = GetOperandAbsNegFloat(op_b, false, instr.fmul.negate_b); @@ -75,21 +73,20 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { value = GetSaturatedFloat(value, instr.alu.saturate_d); + SetInternalFlagsFromFloat(bb, value, instr.generates_cc); SetRegister(bb, instr.gpr0, value); break; } case OpCode::Id::FADD_C: case OpCode::Id::FADD_R: case OpCode::Id::FADD_IMM: { - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in FADD is not implemented"); - op_a = GetOperandAbsNegFloat(op_a, instr.alu.abs_a, instr.alu.negate_a); op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b); Node value = Operation(OperationCode::FAdd, PRECISE, op_a, op_b); value = GetSaturatedFloat(value, instr.alu.saturate_d); + SetInternalFlagsFromFloat(bb, value, instr.generates_cc); SetRegister(bb, instr.gpr0, value); break; } @@ -126,9 +123,6 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { case OpCode::Id::FMNMX_C: case OpCode::Id::FMNMX_R: case OpCode::Id::FMNMX_IMM: { - UNIMPLEMENTED_IF_MSG(instr.generates_cc, - "Condition codes generation in FMNMX is not implemented"); - op_a = GetOperandAbsNegFloat(op_a, instr.alu.abs_a, instr.alu.negate_a); op_b = GetOperandAbsNegFloat(op_b, instr.alu.abs_b, instr.alu.negate_b); @@ -136,9 +130,10 @@ u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { const Node min = Operation(OperationCode::FMin, NO_PRECISE, op_a, op_b); const Node max = Operation(OperationCode::FMax, NO_PRECISE, op_a, op_b); + const Node value = Operation(OperationCode::Select, NO_PRECISE, condition, min, max); - SetRegister(bb, instr.gpr0, - Operation(OperationCode::Select, NO_PRECISE, condition, min, max)); + SetInternalFlagsFromFloat(bb, value, instr.generates_cc); + SetRegister(bb, instr.gpr0, value); break; } case OpCode::Id::RRO_C: -- cgit v1.2.3 From 170c8212bbb10129dfbaed8eb7ab67138c932af2 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Fri, 28 Dec 2018 20:00:36 -0300 Subject: shader_ir: Pass to decoder functions basic block's code --- src/video_core/shader/decode/arithmetic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/video_core/shader/decode/arithmetic.cpp') diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp index 926abcc8e..e7847f614 100644 --- a/src/video_core/shader/decode/arithmetic.cpp +++ b/src/video_core/shader/decode/arithmetic.cpp @@ -13,7 +13,7 @@ using Tegra::Shader::Instruction; using Tegra::Shader::OpCode; using Tegra::Shader::SubOp; -u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, u32 pc) { +u32 ShaderIR::DecodeArithmetic(BasicBlock& bb, const BasicBlock& code, u32 pc) { const Instruction instr = {program_code[pc]}; const auto opcode = OpCode::Decode(instr); -- cgit v1.2.3