diff options
| author | 2018-04-09 23:39:44 -0400 | |
|---|---|---|
| committer | 2018-04-14 16:01:40 -0400 | |
| commit | 86135864da9bbbd5906e96862994bd24f3cd4da5 (patch) | |
| tree | 6e8c52749b512101f9733314a40c1461d6f6c77b /src | |
| parent | shader_bytecode: Add FSETP and KIL to GetInfo. (diff) | |
| download | yuzu-86135864da9bbbd5906e96862994bd24f3cd4da5.tar.gz yuzu-86135864da9bbbd5906e96862994bd24f3cd4da5.tar.xz yuzu-86135864da9bbbd5906e96862994bd24f3cd4da5.zip | |
gl_shader_decompiler: Implement negate, abs, etc. and lots of cleanup.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 59 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 77 |
2 files changed, 96 insertions, 40 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index a4d02e572..dbcd23755 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -56,15 +56,18 @@ union Attribute { | |||
| 56 | Attribute_0 = 8, | 56 | Attribute_0 = 8, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | constexpr Index GetIndex() const { | 59 | union { |
| 60 | return index; | 60 | BitField<22, 2, u64> element; |
| 61 | } | 61 | BitField<24, 6, Index> index; |
| 62 | BitField<47, 3, u64> size; | ||
| 63 | } fmt20; | ||
| 64 | |||
| 65 | union { | ||
| 66 | BitField<30, 2, u64> element; | ||
| 67 | BitField<32, 6, Index> index; | ||
| 68 | } fmt28; | ||
| 62 | 69 | ||
| 63 | public: | ||
| 64 | BitField<24, 6, Index> index; | ||
| 65 | BitField<22, 2, u64> element; | ||
| 66 | BitField<39, 8, u64> reg; | 70 | BitField<39, 8, u64> reg; |
| 67 | BitField<47, 3, u64> size; | ||
| 68 | u64 value; | 71 | u64 value; |
| 69 | }; | 72 | }; |
| 70 | 73 | ||
| @@ -104,6 +107,7 @@ union OpCode { | |||
| 104 | enum class Type { | 107 | enum class Type { |
| 105 | Trivial, | 108 | Trivial, |
| 106 | Arithmetic, | 109 | Arithmetic, |
| 110 | Ffma, | ||
| 107 | Flow, | 111 | Flow, |
| 108 | Memory, | 112 | Memory, |
| 109 | Unknown, | 113 | Unknown, |
| @@ -210,12 +214,11 @@ union OpCode { | |||
| 210 | info_table[Id::TEXS] = {Type::Memory, "texs"}; | 214 | info_table[Id::TEXS] = {Type::Memory, "texs"}; |
| 211 | info_table[Id::LD_A] = {Type::Memory, "ld_a"}; | 215 | info_table[Id::LD_A] = {Type::Memory, "ld_a"}; |
| 212 | info_table[Id::ST_A] = {Type::Memory, "st_a"}; | 216 | info_table[Id::ST_A] = {Type::Memory, "st_a"}; |
| 213 | info_table[Id::IPA] = {Type::Arithmetic, "ipa"}; | ||
| 214 | info_table[Id::MUFU] = {Type::Arithmetic, "mufu"}; | 217 | info_table[Id::MUFU] = {Type::Arithmetic, "mufu"}; |
| 215 | info_table[Id::FFMA_IMM] = {Type::Arithmetic, "ffma_imm"}; | 218 | info_table[Id::FFMA_IMM] = {Type::Ffma, "ffma_imm"}; |
| 216 | info_table[Id::FFMA_CR] = {Type::Arithmetic, "ffma_cr"}; | 219 | info_table[Id::FFMA_CR] = {Type::Ffma, "ffma_cr"}; |
| 217 | info_table[Id::FFMA_RC] = {Type::Arithmetic, "ffma_rc"}; | 220 | info_table[Id::FFMA_RC] = {Type::Ffma, "ffma_rc"}; |
| 218 | info_table[Id::FFMA_RR] = {Type::Arithmetic, "ffma_rr"}; | 221 | info_table[Id::FFMA_RR] = {Type::Ffma, "ffma_rr"}; |
| 219 | info_table[Id::FADD_R] = {Type::Arithmetic, "fadd_r"}; | 222 | info_table[Id::FADD_R] = {Type::Arithmetic, "fadd_r"}; |
| 220 | info_table[Id::FADD_C] = {Type::Arithmetic, "fadd_c"}; | 223 | info_table[Id::FADD_C] = {Type::Arithmetic, "fadd_c"}; |
| 221 | info_table[Id::FADD_IMM] = {Type::Arithmetic, "fadd_imm"}; | 224 | info_table[Id::FADD_IMM] = {Type::Arithmetic, "fadd_imm"}; |
| @@ -225,6 +228,7 @@ union OpCode { | |||
| 225 | info_table[Id::FSETP_C] = {Type::Arithmetic, "fsetp_c"}; | 228 | info_table[Id::FSETP_C] = {Type::Arithmetic, "fsetp_c"}; |
| 226 | info_table[Id::FSETP_R] = {Type::Arithmetic, "fsetp_r"}; | 229 | info_table[Id::FSETP_R] = {Type::Arithmetic, "fsetp_r"}; |
| 227 | info_table[Id::EXIT] = {Type::Trivial, "exit"}; | 230 | info_table[Id::EXIT] = {Type::Trivial, "exit"}; |
| 231 | info_table[Id::IPA] = {Type::Trivial, "ipa"}; | ||
| 228 | info_table[Id::KIL] = {Type::Flow, "kil"}; | 232 | info_table[Id::KIL] = {Type::Flow, "kil"}; |
| 229 | return info_table; | 233 | return info_table; |
| 230 | } | 234 | } |
| @@ -285,16 +289,31 @@ union Instruction { | |||
| 285 | } | 289 | } |
| 286 | 290 | ||
| 287 | OpCode opcode; | 291 | OpCode opcode; |
| 288 | BitField<0, 8, Register> gpr1; | 292 | BitField<0, 8, Register> gpr0; |
| 289 | BitField<8, 8, Register> gpr2; | 293 | BitField<8, 8, Register> gpr8; |
| 290 | BitField<16, 4, Pred> pred; | 294 | BitField<16, 4, Pred> pred; |
| 295 | BitField<20, 8, Register> gpr20; | ||
| 291 | BitField<20, 7, SubOp> sub_op; | 296 | BitField<20, 7, SubOp> sub_op; |
| 292 | BitField<39, 8, Register> gpr3; | 297 | BitField<28, 8, Register> gpr28; |
| 293 | BitField<45, 1, u64> nb; | 298 | BitField<36, 13, u64> imm36; |
| 294 | BitField<46, 1, u64> aa; | 299 | BitField<39, 8, Register> gpr39; |
| 295 | BitField<48, 1, u64> na; | 300 | |
| 296 | BitField<49, 1, u64> ab; | 301 | union { |
| 297 | BitField<50, 1, u64> ad; | 302 | BitField<45, 1, u64> negate_b; |
| 303 | BitField<46, 1, u64> abs_a; | ||
| 304 | BitField<48, 1, u64> negate_a; | ||
| 305 | BitField<49, 1, u64> abs_b; | ||
| 306 | BitField<50, 1, u64> abs_d; | ||
| 307 | } alu; | ||
| 308 | |||
| 309 | union { | ||
| 310 | BitField<48, 1, u64> negate_b; | ||
| 311 | BitField<49, 1, u64> negate_c; | ||
| 312 | } ffma; | ||
| 313 | |||
| 314 | BitField<60, 1, u64> is_b_gpr; | ||
| 315 | BitField<59, 1, u64> is_c_gpr; | ||
| 316 | |||
| 298 | Attribute attribute; | 317 | Attribute attribute; |
| 299 | Uniform uniform; | 318 | Uniform uniform; |
| 300 | 319 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 704b24307..792b4b12e 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -17,6 +17,7 @@ using Tegra::Shader::Attribute; | |||
| 17 | using Tegra::Shader::Instruction; | 17 | using Tegra::Shader::Instruction; |
| 18 | using Tegra::Shader::OpCode; | 18 | using Tegra::Shader::OpCode; |
| 19 | using Tegra::Shader::Register; | 19 | using Tegra::Shader::Register; |
| 20 | using Tegra::Shader::SubOp; | ||
| 20 | using Tegra::Shader::Uniform; | 21 | using Tegra::Shader::Uniform; |
| 21 | 22 | ||
| 22 | constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; | 23 | constexpr u32 PROGRAM_END = MAX_PROGRAM_CODE_LENGTH; |
| @@ -235,31 +236,67 @@ private: | |||
| 235 | 236 | ||
| 236 | switch (OpCode::GetInfo(instr.opcode).type) { | 237 | switch (OpCode::GetInfo(instr.opcode).type) { |
| 237 | case OpCode::Type::Arithmetic: { | 238 | case OpCode::Type::Arithmetic: { |
| 238 | ASSERT(!instr.nb); | 239 | ASSERT(!instr.alu.abs_d, "unimplemented"); |
| 239 | ASSERT(!instr.aa); | ||
| 240 | ASSERT(!instr.na); | ||
| 241 | ASSERT(!instr.ab); | ||
| 242 | ASSERT(!instr.ad); | ||
| 243 | 240 | ||
| 244 | std::string gpr1 = GetRegister(instr.gpr1); | 241 | std::string dest = GetRegister(instr.gpr0); |
| 245 | std::string gpr2 = GetRegister(instr.gpr2); | 242 | std::string op_a = instr.alu.negate_a ? "-" : ""; |
| 246 | std::string uniform = GetUniform(instr.uniform); | 243 | op_a += GetRegister(instr.gpr8); |
| 244 | if (instr.alu.abs_a) { | ||
| 245 | op_a = "abs(" + op_a + ")"; | ||
| 246 | } | ||
| 247 | |||
| 248 | std::string op_b = instr.alu.negate_b ? "-" : ""; | ||
| 249 | if (instr.is_b_gpr) { | ||
| 250 | op_b += GetRegister(instr.gpr20); | ||
| 251 | } else { | ||
| 252 | op_b += GetUniform(instr.uniform); | ||
| 253 | } | ||
| 254 | if (instr.alu.abs_b) { | ||
| 255 | op_b = "abs(" + op_b + ")"; | ||
| 256 | } | ||
| 247 | 257 | ||
| 248 | switch (instr.opcode.EffectiveOpCode()) { | 258 | switch (instr.opcode.EffectiveOpCode()) { |
| 249 | case OpCode::Id::FMUL_C: { | 259 | case OpCode::Id::FMUL_C: |
| 250 | SetDest(0, gpr1, gpr2 + " * " + uniform, 1, 1); | 260 | case OpCode::Id::FMUL_R: { |
| 261 | SetDest(0, dest, op_a + " * " + op_b, 1, 1); | ||
| 262 | break; | ||
| 263 | } | ||
| 264 | case OpCode::Id::FADD_C: | ||
| 265 | case OpCode::Id::FADD_R: { | ||
| 266 | SetDest(0, dest, op_a + " + " + op_b, 1, 1); | ||
| 251 | break; | 267 | break; |
| 252 | } | 268 | } |
| 253 | case OpCode::Id::FADD_C: { | 269 | default: { |
| 254 | SetDest(0, gpr1, gpr2 + " + " + uniform, 1, 1); | 270 | LOG_ERROR(HW_GPU, "Unhandled arithmetic instruction: 0x%02x (%s): 0x%08x", |
| 271 | (int)instr.opcode.EffectiveOpCode(), OpCode::GetInfo(instr.opcode).name, | ||
| 272 | instr.hex); | ||
| 273 | throw DecompileFail("Unhandled instruction"); | ||
| 255 | break; | 274 | break; |
| 256 | } | 275 | } |
| 276 | } | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | case OpCode::Type::Ffma: { | ||
| 280 | ASSERT_MSG(!instr.ffma.negate_b, "untested"); | ||
| 281 | ASSERT_MSG(!instr.ffma.negate_c, "untested"); | ||
| 282 | |||
| 283 | std::string dest = GetRegister(instr.gpr0); | ||
| 284 | std::string op_a = GetRegister(instr.gpr8); | ||
| 285 | |||
| 286 | std::string op_b = instr.ffma.negate_b ? "-" : ""; | ||
| 287 | op_b += GetUniform(instr.uniform); | ||
| 288 | |||
| 289 | std::string op_c = instr.ffma.negate_c ? "-" : ""; | ||
| 290 | op_c += GetRegister(instr.gpr39); | ||
| 291 | |||
| 292 | switch (instr.opcode.EffectiveOpCode()) { | ||
| 257 | case OpCode::Id::FFMA_CR: { | 293 | case OpCode::Id::FFMA_CR: { |
| 258 | SetDest(0, gpr1, gpr2 + " * " + uniform + " + " + GetRegister(instr.gpr3), 1, 1); | 294 | SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1); |
| 259 | break; | 295 | break; |
| 260 | } | 296 | } |
| 297 | |||
| 261 | default: { | 298 | default: { |
| 262 | LOG_ERROR(HW_GPU, "Unhandled arithmetic instruction: 0x%02x (%s): 0x%08x", | 299 | LOG_ERROR(HW_GPU, "Unhandled arithmetic FFMA instruction: 0x%02x (%s): 0x%08x", |
| 263 | (int)instr.opcode.EffectiveOpCode(), OpCode::GetInfo(instr.opcode).name, | 300 | (int)instr.opcode.EffectiveOpCode(), OpCode::GetInfo(instr.opcode).name, |
| 264 | instr.hex); | 301 | instr.hex); |
| 265 | throw DecompileFail("Unhandled instruction"); | 302 | throw DecompileFail("Unhandled instruction"); |
| @@ -269,18 +306,18 @@ private: | |||
| 269 | break; | 306 | break; |
| 270 | } | 307 | } |
| 271 | case OpCode::Type::Memory: { | 308 | case OpCode::Type::Memory: { |
| 272 | ASSERT(instr.attribute.size == 0); | 309 | std::string gpr0 = GetRegister(instr.gpr0); |
| 273 | 310 | const Attribute::Index attribute = instr.attribute.fmt20.index; | |
| 274 | std::string gpr1 = GetRegister(instr.gpr1); | ||
| 275 | const Attribute::Index attribute = instr.attribute.GetIndex(); | ||
| 276 | 311 | ||
| 277 | switch (instr.opcode.EffectiveOpCode()) { | 312 | switch (instr.opcode.EffectiveOpCode()) { |
| 278 | case OpCode::Id::LD_A: { | 313 | case OpCode::Id::LD_A: { |
| 279 | SetDest(instr.attribute.element, gpr1, GetInputAttribute(attribute), 1, 4); | 314 | ASSERT(instr.attribute.fmt20.size == 0); |
| 315 | SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4); | ||
| 280 | break; | 316 | break; |
| 281 | } | 317 | } |
| 282 | case OpCode::Id::ST_A: { | 318 | case OpCode::Id::ST_A: { |
| 283 | SetDest(instr.attribute.element, GetOutputAttribute(attribute), gpr1, 4, 1); | 319 | ASSERT(instr.attribute.fmt20.size == 0); |
| 320 | SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1); | ||
| 284 | break; | 321 | break; |
| 285 | } | 322 | } |
| 286 | default: { | 323 | default: { |