Fragment Shader recompiler comments

Don't expect changes due to this commit.
This commit is contained in:
Alexandro Sánchez Bach 2014-08-18 22:07:52 +02:00
parent b23a5f2312
commit cf9769fe65
4 changed files with 166 additions and 98 deletions

View File

@ -267,9 +267,8 @@ std::string GLFragmentDecompilerThread::BuildCode()
std::string p; std::string p;
for (u32 i = 0; i<m_parr.params.size(); ++i) for (auto& param : m_parr.params) {
{ p += param.Format();
p += m_parr.params[i].Format();
} }
return std::string("#version 330\n" return std::string("#version 330\n"
@ -321,115 +320,114 @@ void GLFragmentDecompilerThread::Task()
switch(opcode) switch(opcode)
{ {
case 0x00: break; //NOP case RSX_FP_OPCODE_NOP: break;
case 0x01: SetDst("$0"); break; //MOV case RSX_FP_OPCODE_MOV: SetDst("$0"); break;
case 0x02: SetDst("($0 * $1)"); break; //MUL case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); break;
case 0x03: SetDst("($0 + $1)"); break; //ADD case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); break;
case 0x04: SetDst("($0 * $1 + $2)"); break; //MAD case RSX_FP_OPCODE_MAD: SetDst("($0 * $1 + $2)"); break;
case 0x05: SetDst("vec4(dot($0.xyz, $1.xyz))"); break; // DP3 case RSX_FP_OPCODE_DP3: SetDst("vec4(dot($0.xyz, $1.xyz))"); break;
case 0x06: SetDst("vec4(dot($0, $1))"); break; // DP4 case RSX_FP_OPCODE_DP4: SetDst("vec4(dot($0, $1))"); break;
case 0x07: SetDst("vec4(distance($0, $1))"); break; // DST case RSX_FP_OPCODE_DST: SetDst("vec4(distance($0, $1))"); break;
case 0x08: SetDst("min($0, $1)"); break; // MIN case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); break;
case 0x09: SetDst("max($0, $1)"); break; // MAX case RSX_FP_OPCODE_MAX: SetDst("max($0, $1)"); break;
case 0x0a: SetDst("vec4(lessThan($0, $1))"); break; // SLT case RSX_FP_OPCODE_SLT: SetDst("vec4(lessThan($0, $1))"); break;
case 0x0b: SetDst("vec4(greaterThanEqual($0, $1))"); break; // SGE case RSX_FP_OPCODE_SGE: SetDst("vec4(greaterThanEqual($0, $1))"); break;
case 0x0c: SetDst("vec4(lessThanEqual($0, $1))"); break; // SLE case RSX_FP_OPCODE_SLE: SetDst("vec4(lessThanEqual($0, $1))"); break;
case 0x0d: SetDst("vec4(greaterThan($0, $1))"); break; // SGT case RSX_FP_OPCODE_SGT: SetDst("vec4(greaterThan($0, $1))"); break;
case 0x0e: SetDst("vec4(notEqual($0, $1))"); break; // SNE case RSX_FP_OPCODE_SNE: SetDst("vec4(notEqual($0, $1))"); break;
case 0x0f: SetDst("vec4(equal($0, $1))"); break; // SEQ case RSX_FP_OPCODE_SEQ: SetDst("vec4(equal($0, $1))"); break;
case 0x10: SetDst("fract($0)"); break; // FRC case RSX_FP_OPCODE_FRC: SetDst("fract($0)"); break;
case 0x11: SetDst("floor($0)"); break; // FLR case RSX_FP_OPCODE_FLR: SetDst("floor($0)"); break;
case 0x12: SetDst("discard", false); break; // KIL (kill fragment) case RSX_FP_OPCODE_KIL: SetDst("discard", false); break;
//case 0x13: break; // PK4 (pack four signed 8-bit values) //case RSX_FP_OPCODE_PK4: break;
//case 0x14: break; // UP4 (unpack four signed 8-bit values) //case RSX_FP_OPCODE_UP4: break;
case 0x15: SetDst("dFdx($0)"); break; // DDX case RSX_FP_OPCODE_DDX: SetDst("dFdx($0)"); break;
case 0x16: SetDst("dFdy($0)"); break; // DDY case RSX_FP_OPCODE_DDY: SetDst("dFdy($0)"); break;
case 0x17: SetDst("texture($t, $0.xy)"); break; // TEX (texture lookup) case RSX_FP_OPCODE_TEX: SetDst("texture($t, $0.xy)"); break;
//case 0x18: break; // TXP (projective texture lookup) //case RSX_FP_OPCODE_TXP: break;
//case 0x19: break; // TXD (texture lookup with derivatives) //case RSX_FP_OPCODE_TXD: break;
case 0x1a: SetDst("(1 / $0)"); break; // RCP case RSX_FP_OPCODE_RCP: SetDst("(1 / $0)"); break;
case 0x1b: SetDst("inversesqrt(abs($0))"); break; // RSQ case RSX_FP_OPCODE_RSQ: SetDst("inversesqrt(abs($0))"); break;
case 0x1c: SetDst("exp2($0)"); break; // EX2 case RSX_FP_OPCODE_EX2: SetDst("exp2($0)"); break;
case 0x1d: SetDst("log2($0)"); break; // LG2 case RSX_FP_OPCODE_LG2: SetDst("log2($0)"); break;
case 0x1e: SetDst("vec4(1.0, $0.x, ($0.x > 0 ? exp2($0.w * log2($0.y)) : 0.0), 1.0)"); break; // LIT (compute light coefficients) case RSX_FP_OPCODE_LIT: SetDst("vec4(1.0, $0.x, ($0.x > 0 ? exp2($0.w * log2($0.y)) : 0.0), 1.0)"); break;
case 0x1f: SetDst("($0 * ($1 - $2) + $2)"); break; // LRP (linear interpolation) case RSX_FP_OPCODE_LRP: SetDst("($0 * ($1 - $2) + $2)"); break;
case 0x20: SetDst("vec4(equal($0, vec4(1.0)))"); break; // STR (set on true) case RSX_FP_OPCODE_STR: SetDst("vec4(equal($0, vec4(1.0)))"); break;
case 0x21: SetDst("vec4(equal($0, vec4(0.0)))"); break; // SFL (set on false) case RSX_FP_OPCODE_SFL: SetDst("vec4(equal($0, vec4(0.0)))"); break;
case 0x22: SetDst("cos($0)"); break; // COS case RSX_FP_OPCODE_COS: SetDst("cos($0)"); break;
case 0x23: SetDst("sin($0)"); break; // SIN case RSX_FP_OPCODE_SIN: SetDst("sin($0)"); break;
//case 0x24: break; // PK2 (pack two 16-bit floats) //case RSX_FP_OPCODE_PK2: break;
//case 0x25: break; // UP2 (unpack two 16-bit floats) //case RSX_FP_OPCODE_UP2: break;
case 0x26: SetDst("pow($0, $1)"); break; // POW case RSX_FP_OPCODE_POW: SetDst("pow($0, $1)"); break;
//case 0x27: break; // PKB //case RSX_FP_OPCODE_PKB: break;
//case 0x28: break; // UPB //case RSX_FP_OPCODE_UPB: break;
//case 0x29: break; // PK16 //case RSX_FP_OPCODE_PK16: break;
//case 0x2a: break; // UP16 //case RSX_FP_OPCODE_UP16: break;
//case 0x2b: break; // BEM //case RSX_FP_OPCODE_BEM: break;
//case 0x2c: break; // PKG //case RSX_FP_OPCODE_PKG: break;
//case 0x2d: break; // UPG //case RSX_FP_OPCODE_UPG: break;
case 0x2e: SetDst("($0.x * $1.x + $0.y * $1.y + $2.x)"); break; // DP2A (2-component dot product and add) case RSX_FP_OPCODE_DP2A: SetDst("($0.x * $1.x + $0.y * $1.y + $2.x)"); break;
//case 0x2f: break; // TXL (texture lookup with LOD) //case RSX_FP_OPCODE_TXL: break;
//case 0x30: break; //case RSX_FP_OPCODE_TXB: break;
//case 0x31: break; // TXB (texture lookup with bias) //case RSX_FP_OPCODE_TEXBEM: break;
//case 0x33: break; // TEXBEM //case RSX_FP_OPCODE_TXPBEM: break;
//case 0x34: break; // TXPBEM //case RSX_FP_OPCODE_BEMLUM: break;
//case 0x35: break; // BEMLUM case RSX_FP_OPCODE_REFL: SetDst("($0 - 2.0 * $1 * dot($0, $1))"); break;
case 0x36: SetDst("($0 - 2.0 * $1 * dot($0, $1))"); break; // RFL (reflection vector) //case RSX_FP_OPCODE_TIMESWTEX: break;
//case 0x37: break; // TIMESWTEX case RSX_FP_OPCODE_DP2: SetDst("vec4(dot($0.xy, $1.xy))"); break;
case 0x38: SetDst("vec4(dot($0.xy, $1.xy))"); break; // DP2 case RSX_FP_OPCODE_NRM: SetDst("normalize($0.xyz)"); break;
case 0x39: SetDst("normalize($0.xyz)"); break; // NRM case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); break;
case 0x3a: SetDst("($0 / $1)"); break; // DIV case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1))"); break;
case 0x3b: SetDst("($0 / sqrt($1))"); break; // DIVSQ case RSX_FP_OPCODE_LIF: SetDst("vec4(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); break;
case 0x3c: SetDst("vec4(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); break; // LIF case RSX_FP_OPCODE_FENCT: break;
case 0x3d: break; // FENCT case RSX_FP_OPCODE_FENCB: break;
case 0x3e: break; // FENCB
case 0x40: SetDst("break"); break; //BRK case RSX_FP_OPCODE_BRK: SetDst("break"); break;
//case 0x41: break; //CAL //case RSX_FP_OPCODE_CAL: break;
case 0x42: case RSX_FP_OPCODE_IFE:
AddCode("if($cond)"); //IF AddCode("if($cond)");
m_else_offsets.push_back(src1.else_offset << 2); m_else_offsets.push_back(src1.else_offset << 2);
m_end_offsets.push_back(src2.end_offset << 2); m_end_offsets.push_back(src2.end_offset << 2);
AddCode("{"); AddCode("{");
m_code_level++; m_code_level++;
break; break;
case 0x43: //LOOP case RSX_FP_OPCODE_LOOP:
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt)
{ {
AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //LOOP", AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //LOOP",
m_loop_count, src1.rep2, m_loop_count, src1.rep1, m_loop_count, src1.rep3, src2.end_offset)); m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset));
} }
else else
{ {
AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP", AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) //LOOP",
m_loop_count, src1.rep2, m_loop_count, src1.rep1, m_loop_count, src1.rep3)); m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment));
m_loop_count++; m_loop_count++;
m_end_offsets.push_back(src2.end_offset << 2); m_end_offsets.push_back(src2.end_offset << 2);
AddCode("{"); AddCode("{");
m_code_level++; m_code_level++;
} }
break; break;
case 0x44: //REP case RSX_FP_OPCODE_REP:
if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt) if(!src0.exec_if_eq && !src0.exec_if_gr && !src0.exec_if_lt)
{ {
AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //REP", AddCode(fmt::Format("$ifcond for(int i%u = %u; i%u < %u; i%u += %u) {} //-> %u //REP",
m_loop_count, src1.rep2, m_loop_count, src1.rep1, m_loop_count, src1.rep3, src2.end_offset)); m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment, src2.end_offset));
} }
else else
{ {
AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP", AddCode(fmt::Format("if($cond) for(int i%u = %u; i%u < %u; i%u += %u) //REP",
m_loop_count, src1.rep2, m_loop_count, src1.rep1, m_loop_count, src1.rep3)); m_loop_count, src1.init_counter, m_loop_count, src1.end_counter, m_loop_count, src1.increment));
m_loop_count++; m_loop_count++;
m_end_offsets.push_back(src2.end_offset << 2); m_end_offsets.push_back(src2.end_offset << 2);
AddCode("{"); AddCode("{");
m_code_level++; m_code_level++;
} }
break; break;
//case 0x45: SetDst("return"); break; //RET //case RSX_FP_OPCODE_RET: SetDst("return"); break;
default: default:
LOG_ERROR(RSX, "Unknown fp opcode 0x%x (inst %d)", opcode, m_size / (4 * 4)); LOG_ERROR(RSX, "Unknown fp opcode 0x%x (inst %d)", opcode, m_size / (4 * 4));
@ -543,10 +541,9 @@ void GLShaderProgram::Compile()
void GLShaderProgram::Delete() void GLShaderProgram::Delete()
{ {
for (u32 i = 0; i<m_parr.params.size(); ++i) for (auto& param : m_parr.params) {
{ param.items.clear();
m_parr.params[i].items.clear(); param.type.clear();
m_parr.params[i].type.clear();
} }
m_parr.params.clear(); m_parr.params.clear();

View File

@ -10,21 +10,21 @@ struct GLFragmentDecompilerThread : public ThreadBase
struct struct
{ {
u32 end : 1; u32 end : 1; // Set to 1 if this is the last instruction
u32 dest_reg : 6; u32 dest_reg : 6; // Destination register index
u32 fp16 : 1; u32 fp16 : 1; // Destination is a half register (H0 to H47)
u32 set_cond : 1; u32 set_cond : 1; // Condition Code Registers (CC0 and CC1) are updated
u32 mask_x : 1; u32 mask_x : 1;
u32 mask_y : 1; u32 mask_y : 1;
u32 mask_z : 1; u32 mask_z : 1;
u32 mask_w : 1; u32 mask_w : 1;
u32 src_attr_reg_num : 4; u32 src_attr_reg_num : 4;
u32 tex_num : 4; u32 tex_num : 4;
u32 exp_tex : 1; u32 exp_tex : 1; // _bx2
u32 prec : 2; u32 prec : 2;
u32 opcode : 6; u32 opcode : 6;
u32 no_dest : 1; u32 no_dest : 1;
u32 saturate : 1; u32 saturate : 1; // _sat
}; };
} dst; } dst;
@ -82,13 +82,14 @@ struct GLFragmentDecompilerThread : public ThreadBase
u32 : 1; u32 : 1;
}; };
// LOOP, REP
struct struct
{ {
u32 : 2; u32 : 2;
u32 rep1 : 8; u32 end_counter : 8; // End counter value for LOOP or rep count for REP
u32 rep2 : 8; u32 init_counter : 8; // Initial counter value for LOOP
u32 : 1; u32 : 1;
u32 rep3 : 8; u32 increment : 8; // Increment value for LOOP
}; };
} src1; } src1;

View File

@ -175,11 +175,11 @@ std::string GLVertexDecompilerThread::GetFunc()
{ {
std::string name = "func$a"; std::string name = "func$a";
for(uint i=0; i<m_funcs.size(); ++i) for (const auto& func : m_funcs) {
{ if (func.name.compare(name) == 0) {
if(m_funcs[i].name.compare(name) == 0)
return name + "()"; return name + "()";
} }
}
m_funcs.emplace_back(); m_funcs.emplace_back();
FuncInfo &idx = m_funcs.back(); FuncInfo &idx = m_funcs.back();
@ -380,9 +380,8 @@ std::string GLVertexDecompilerThread::BuildCode()
std::string p; std::string p;
for (u32 i = 0; i<m_parr.params.size(); ++i) for (auto& param : m_parr.params) {
{ p += param.Format();
p += m_parr.params[i].Format();
} }
std::string fp; std::string fp;

View File

@ -1,5 +1,76 @@
#pragma once #pragma once
enum
{
RSX_FP_OPCODE_NOP = 0x00, // No-Operation
RSX_FP_OPCODE_MOV = 0x01, // Move
RSX_FP_OPCODE_MUL = 0x02, // Multiply
RSX_FP_OPCODE_ADD = 0x03, // Add
RSX_FP_OPCODE_MAD = 0x04, // Multiply-Add
RSX_FP_OPCODE_DP3 = 0x05, // 3-component Dot Product
RSX_FP_OPCODE_DP4 = 0x06, // 4-component Dot Product
RSX_FP_OPCODE_DST = 0x07, // Distance
RSX_FP_OPCODE_MIN = 0x08, // Minimum
RSX_FP_OPCODE_MAX = 0x09, // Maximum
RSX_FP_OPCODE_SLT = 0x0A, // Set-If-LessThan
RSX_FP_OPCODE_SGE = 0x0B, // Set-If-GreaterEqual
RSX_FP_OPCODE_SLE = 0x0C, // Set-If-LessEqual
RSX_FP_OPCODE_SGT = 0x0D, // Set-If-GreaterThan
RSX_FP_OPCODE_SNE = 0x0E, // Set-If-NotEqual
RSX_FP_OPCODE_SEQ = 0x0F, // Set-If-Equal
RSX_FP_OPCODE_FRC = 0x10, // Fraction (fract)
RSX_FP_OPCODE_FLR = 0x11, // Floor
RSX_FP_OPCODE_KIL = 0x12, // Kill fragment
RSX_FP_OPCODE_PK4 = 0x13, // Pack four signed 8-bit values
RSX_FP_OPCODE_UP4 = 0x14, // Unpack four signed 8-bit values
RSX_FP_OPCODE_DDX = 0x15, // Partial-derivative in x (Screen space derivative w.r.t. x)
RSX_FP_OPCODE_DDY = 0x16, // Partial-derivative in y (Screen space derivative w.r.t. y)
RSX_FP_OPCODE_TEX = 0x17, // Texture lookup
RSX_FP_OPCODE_TXP = 0x18, // Texture sample with projection (Projective texture lookup)
RSX_FP_OPCODE_TXD = 0x19, // Texture sample with partial differentiation (Texture lookup with derivatives)
RSX_FP_OPCODE_RCP = 0x1A, // Reciprocal
RSX_FP_OPCODE_RSQ = 0x1B, // Reciprocal Square Root
RSX_FP_OPCODE_EX2 = 0x1C, // Exponentiation base 2
RSX_FP_OPCODE_LG2 = 0x1D, // Log base 2
RSX_FP_OPCODE_LIT = 0x1E, // Lighting coefficients
RSX_FP_OPCODE_LRP = 0x1F, // Linear Interpolation
RSX_FP_OPCODE_STR = 0x20, // Set-If-True
RSX_FP_OPCODE_SFL = 0x21, // Set-If-False
RSX_FP_OPCODE_COS = 0x22, // Cosine
RSX_FP_OPCODE_SIN = 0x23, // Sine
RSX_FP_OPCODE_PK2 = 0x24, // Pack two 16-bit floats
RSX_FP_OPCODE_UP2 = 0x25, // Unpack two 16-bit floats
RSX_FP_OPCODE_POW = 0x26, // Power
RSX_FP_OPCODE_PKB = 0x27, // Pack bytes
RSX_FP_OPCODE_UPB = 0x28, // Unpack bytes
RSX_FP_OPCODE_PK16 = 0x29, // Pack 16 bits
RSX_FP_OPCODE_UP16 = 0x2A, // Unpack 16
RSX_FP_OPCODE_BEM = 0x2B, // Bump-environment map (a.k.a. 2D coordinate transform)
RSX_FP_OPCODE_PKG = 0x2C, // Pack with sRGB transformation
RSX_FP_OPCODE_UPG = 0x2D, // Unpack gamma
RSX_FP_OPCODE_DP2A = 0x2E, // 2-component dot product with scalar addition
RSX_FP_OPCODE_TXL = 0x2F, // Texture sample with LOD
RSX_FP_OPCODE_TXB = 0x31, // Texture sample with bias
RSX_FP_OPCODE_TEXBEM = 0x33,
RSX_FP_OPCODE_TXPBEM = 0x34,
RSX_FP_OPCODE_BEMLUM = 0x35,
RSX_FP_OPCODE_REFL = 0x36, // Reflection vector
RSX_FP_OPCODE_TIMESWTEX = 0x37,
RSX_FP_OPCODE_DP2 = 0x38, // 2-component dot product
RSX_FP_OPCODE_NRM = 0x39, // Normalize
RSX_FP_OPCODE_DIV = 0x3A, // Division
RSX_FP_OPCODE_DIVSQ = 0x3B, // Divide by Square Root
RSX_FP_OPCODE_LIF = 0x3C, // Final part of LIT
RSX_FP_OPCODE_FENCT = 0x3D, // Fence T?
RSX_FP_OPCODE_FENCB = 0x3E, // Fence B?
RSX_FP_OPCODE_BRK = 0x40, // Break
RSX_FP_OPCODE_CAL = 0x41, // Subroutine call
RSX_FP_OPCODE_IFE = 0x42, // If
RSX_FP_OPCODE_LOOP = 0x43, // Loop
RSX_FP_OPCODE_REP = 0x44, // Repeat
RSX_FP_OPCODE_RET = 0x45, // Return
};
struct RSXShaderProgram struct RSXShaderProgram
{ {
u32 size; u32 size;