summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_core/engines/shader_bytecode.h47
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp107
2 files changed, 133 insertions, 21 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 88b4d0bac..7e1de0fa1 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -240,6 +240,41 @@ enum class FlowCondition : u64 {
240 Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for? 240 Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for?
241}; 241};
242 242
243enum class ControlCode : u64 {
244 F = 0,
245 LT = 1,
246 EQ = 2,
247 LE = 3,
248 GT = 4,
249 NE = 5,
250 GE = 6,
251 Num = 7,
252 Nan = 8,
253 LTU = 9,
254 EQU = 10,
255 LEU = 11,
256 GTU = 12,
257 NEU = 13,
258 GEU = 14,
259 //
260 OFF = 16,
261 LO = 17,
262 SFF = 18,
263 LS = 19,
264 HI = 20,
265 SFT = 21,
266 HS = 22,
267 OFT = 23,
268 CSM_TA = 24,
269 CSM_TR = 25,
270 CSM_MX = 26,
271 FCSM_TA = 27,
272 FCSM_TR = 28,
273 FCSM_MX = 29,
274 RLE = 30,
275 RGT = 31,
276};
277
243enum class PredicateResultMode : u64 { 278enum class PredicateResultMode : u64 {
244 None = 0x0, 279 None = 0x0,
245 NotZero = 0x3, 280 NotZero = 0x3,
@@ -555,6 +590,15 @@ union Instruction {
555 } pset; 590 } pset;
556 591
557 union { 592 union {
593 BitField<0, 3, u64> pred0;
594 BitField<3, 3, u64> pred3;
595 BitField<8, 5, ControlCode> cc; // flag in cc
596 BitField<39, 3, u64> pred39;
597 BitField<42, 1, u64> neg_pred39;
598 BitField<45, 4, PredOperation> op; // op with pred39
599 } csetp;
600
601 union {
558 BitField<39, 3, u64> pred39; 602 BitField<39, 3, u64> pred39;
559 BitField<42, 1, u64> neg_pred; 603 BitField<42, 1, u64> neg_pred;
560 BitField<43, 1, u64> neg_a; 604 BitField<43, 1, u64> neg_a;
@@ -881,6 +925,7 @@ union Instruction {
881 BitField<36, 5, u64> index; 925 BitField<36, 5, u64> index;
882 } cbuf36; 926 } cbuf36;
883 927
928 BitField<47, 1, u64> generates_cc;
884 BitField<61, 1, u64> is_b_imm; 929 BitField<61, 1, u64> is_b_imm;
885 BitField<60, 1, u64> is_b_gpr; 930 BitField<60, 1, u64> is_b_gpr;
886 BitField<59, 1, u64> is_c_gpr; 931 BitField<59, 1, u64> is_c_gpr;
@@ -1005,6 +1050,7 @@ public:
1005 ISET_IMM, 1050 ISET_IMM,
1006 PSETP, 1051 PSETP,
1007 PSET, 1052 PSET,
1053 CSETP,
1008 XMAD_IMM, 1054 XMAD_IMM,
1009 XMAD_CR, 1055 XMAD_CR,
1010 XMAD_RC, 1056 XMAD_RC,
@@ -1241,6 +1287,7 @@ private:
1241 INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"), 1287 INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"),
1242 INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"), 1288 INST("0101000010001---", Id::PSET, Type::PredicateSetRegister, "PSET"),
1243 INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), 1289 INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
1290 INST("010100001010----", Id::CSETP, Type::PredicateSetPredicate, "CSETP"),
1244 INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"), 1291 INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"),
1245 INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"), 1292 INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"),
1246 INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"), 1293 INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"),
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index cca6cc6ff..393ab5eab 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -236,6 +236,14 @@ private:
236 const std::string& suffix; 236 const std::string& suffix;
237}; 237};
238 238
239enum class InternalFlag : u64 {
240 ZeroFlag = 0,
241 CarryFlag = 1,
242 OverflowFlag = 2,
243 NaNFlag = 3,
244 Amount
245};
246
239/** 247/**
240 * Used to manage shader registers that are emulated with GLSL. This class keeps track of the state 248 * Used to manage shader registers that are emulated with GLSL. This class keeps track of the state
241 * of all registers (e.g. whether they are currently being used as Floats or Integers), and 249 * of all registers (e.g. whether they are currently being used as Floats or Integers), and
@@ -329,13 +337,19 @@ public:
329 void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem, 337 void SetRegisterToInteger(const Register& reg, bool is_signed, u64 elem,
330 const std::string& value, u64 dest_num_components, 338 const std::string& value, u64 dest_num_components,
331 u64 value_num_components, bool is_saturated = false, 339 u64 value_num_components, bool is_saturated = false,
332 u64 dest_elem = 0, Register::Size size = Register::Size::Word) { 340 u64 dest_elem = 0, Register::Size size = Register::Size::Word,
341 bool sets_cc = false) {
333 ASSERT_MSG(!is_saturated, "Unimplemented"); 342 ASSERT_MSG(!is_saturated, "Unimplemented");
334 343
335 const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"}; 344 const std::string func{is_signed ? "intBitsToFloat" : "uintBitsToFloat"};
336 345
337 SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')', 346 SetRegister(reg, elem, func + '(' + ConvertIntegerSize(value, size) + ')',
338 dest_num_components, value_num_components, dest_elem); 347 dest_num_components, value_num_components, dest_elem);
348
349 if (sets_cc) {
350 const std::string zero_condition = "( " + ConvertIntegerSize(value, size) + " == 0 )";
351 SetInternalFlag(InternalFlag::ZeroFlag, zero_condition);
352 }
339 } 353 }
340 354
341 /** 355 /**
@@ -352,6 +366,26 @@ public:
352 shader.AddLine(dest + " = " + src + ';'); 366 shader.AddLine(dest + " = " + src + ';');
353 } 367 }
354 368
369 std::string GetControlCode(const Tegra::Shader::ControlCode cc) const {
370 switch (cc) {
371 case Tegra::Shader::ControlCode::NEU:
372 return "!(" + GetInternalFlag(InternalFlag::ZeroFlag) + ')';
373 default:
374 LOG_CRITICAL(HW_GPU, "Unimplemented Control Code {}", static_cast<u32>(cc));
375 UNREACHABLE();
376 return "false";
377 }
378 }
379
380 std::string GetInternalFlag(const InternalFlag ii) const {
381 const u32 code = static_cast<u32>(ii);
382 return "internalFlag_" + std::to_string(code) + suffix;
383 }
384
385 void SetInternalFlag(const InternalFlag ii, const std::string& value) const {
386 shader.AddLine(GetInternalFlag(ii) + " = " + value + ';');
387 }
388
355 /** 389 /**
356 * Writes code that does a output attribute assignment to register operation. Output attributes 390 * Writes code that does a output attribute assignment to register operation. Output attributes
357 * are stored as floats, so this may require conversion. 391 * are stored as floats, so this may require conversion.
@@ -415,6 +449,12 @@ public:
415 } 449 }
416 declarations.AddNewLine(); 450 declarations.AddNewLine();
417 451
452 for (u32 ii = 0; ii < static_cast<u64>(InternalFlag::Amount); ii++) {
453 const InternalFlag code = static_cast<InternalFlag>(ii);
454 declarations.AddLine("bool " + GetInternalFlag(code) + " = false;");
455 }
456 declarations.AddNewLine();
457
418 for (const auto element : declr_input_attribute) { 458 for (const auto element : declr_input_attribute) {
419 // TODO(bunnei): Use proper number of elements for these 459 // TODO(bunnei): Use proper number of elements for these
420 u32 idx = 460 u32 idx =
@@ -1620,7 +1660,8 @@ private:
1620 } 1660 }
1621 1661
1622 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1, 1662 regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_output_signed, 0, op_a, 1,
1623 1, instr.alu.saturate_d, 0, instr.conversion.dest_size); 1663 1, instr.alu.saturate_d, 0, instr.conversion.dest_size,
1664 instr.generates_cc.Value() != 0);
1624 break; 1665 break;
1625 } 1666 }
1626 case OpCode::Id::I2F_R: 1667 case OpCode::Id::I2F_R:
@@ -2277,31 +2318,55 @@ private:
2277 break; 2318 break;
2278 } 2319 }
2279 case OpCode::Type::PredicateSetPredicate: { 2320 case OpCode::Type::PredicateSetPredicate: {
2280 const std::string op_a = 2321 switch (opcode->GetId()) {
2281 GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0); 2322 case OpCode::Id::PSETP: {
2282 const std::string op_b = 2323 const std::string op_a =
2283 GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0); 2324 GetPredicateCondition(instr.psetp.pred12, instr.psetp.neg_pred12 != 0);
2325 const std::string op_b =
2326 GetPredicateCondition(instr.psetp.pred29, instr.psetp.neg_pred29 != 0);
2284 2327
2285 // We can't use the constant predicate as destination. 2328 // We can't use the constant predicate as destination.
2286 ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); 2329 ASSERT(instr.psetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
2287 2330
2288 const std::string second_pred = 2331 const std::string second_pred =
2289 GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0); 2332 GetPredicateCondition(instr.psetp.pred39, instr.psetp.neg_pred39 != 0);
2290 2333
2291 const std::string combiner = GetPredicateCombiner(instr.psetp.op); 2334 const std::string combiner = GetPredicateCombiner(instr.psetp.op);
2292 2335
2293 const std::string predicate = 2336 const std::string predicate =
2294 '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')'; 2337 '(' + op_a + ") " + GetPredicateCombiner(instr.psetp.cond) + " (" + op_b + ')';
2295 2338
2296 // Set the primary predicate to the result of Predicate OP SecondPredicate 2339 // Set the primary predicate to the result of Predicate OP SecondPredicate
2297 SetPredicate(instr.psetp.pred3, 2340 SetPredicate(instr.psetp.pred3,
2298 '(' + predicate + ") " + combiner + " (" + second_pred + ')'); 2341 '(' + predicate + ") " + combiner + " (" + second_pred + ')');
2299 2342
2300 if (instr.psetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { 2343 if (instr.psetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
2301 // Set the secondary predicate to the result of !Predicate OP SecondPredicate, 2344 // Set the secondary predicate to the result of !Predicate OP SecondPredicate,
2302 // if enabled 2345 // if enabled
2303 SetPredicate(instr.psetp.pred0, 2346 SetPredicate(instr.psetp.pred0,
2304 "!(" + predicate + ") " + combiner + " (" + second_pred + ')'); 2347 "!(" + predicate + ") " + combiner + " (" + second_pred + ')');
2348 }
2349 break;
2350 }
2351 case OpCode::Id::CSETP: {
2352 const std::string pred =
2353 GetPredicateCondition(instr.csetp.pred39, instr.csetp.neg_pred39 != 0);
2354 const std::string combiner = GetPredicateCombiner(instr.csetp.op);
2355 const std::string controlCode = regs.GetControlCode(instr.csetp.cc);
2356 if (instr.csetp.pred3 != static_cast<u64>(Pred::UnusedIndex)) {
2357 SetPredicate(instr.csetp.pred3,
2358 '(' + controlCode + ") " + combiner + " (" + pred + ')');
2359 }
2360 if (instr.csetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
2361 SetPredicate(instr.csetp.pred0,
2362 "!(" + controlCode + ") " + combiner + " (" + pred + ')');
2363 }
2364 break;
2365 }
2366 default: {
2367 LOG_CRITICAL(HW_GPU, "Unhandled predicate instruction: {}", opcode->GetName());
2368 UNREACHABLE();
2369 }
2305 } 2370 }
2306 break; 2371 break;
2307 } 2372 }