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