half_set.cpp 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. // Copyright 2018 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include "common/assert.h"
  6. #include "common/common_types.h"
  7. #include "common/logging/log.h"
  8. #include "video_core/engines/shader_bytecode.h"
  9. #include "video_core/shader/shader_ir.h"
  10. namespace VideoCommon::Shader {
  11. using Tegra::Shader::Instruction;
  12. using Tegra::Shader::OpCode;
  13. u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) {
  14. const Instruction instr = {program_code[pc]};
  15. const auto opcode = OpCode::Decode(instr);
  16. if (instr.hset2.ftz != 0) {
  17. LOG_WARNING(HW_GPU, "{} FTZ not implemented", opcode->get().GetName());
  18. }
  19. Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a);
  20. op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a);
  21. Node op_b = [&]() {
  22. switch (opcode->get().GetId()) {
  23. case OpCode::Id::HSET2_R:
  24. return GetRegister(instr.gpr20);
  25. default:
  26. UNREACHABLE();
  27. return Immediate(0);
  28. }
  29. }();
  30. op_b = UnpackHalfFloat(op_b, instr.hset2.type_b);
  31. op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b);
  32. const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred);
  33. const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, op_a, op_b);
  34. const OperationCode combiner = GetPredicateCombiner(instr.hset2.op);
  35. // HSET2 operates on each half float in the pack.
  36. std::array<Node, 2> values;
  37. for (u32 i = 0; i < 2; ++i) {
  38. const u32 raw_value = instr.hset2.bf ? 0x3c00 : 0xffff;
  39. const Node true_value = Immediate(raw_value << (i * 16));
  40. const Node false_value = Immediate(0);
  41. const Node comparison =
  42. Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i));
  43. const Node predicate = Operation(combiner, comparison, second_pred);
  44. values[i] =
  45. Operation(OperationCode::Select, NO_PRECISE, predicate, true_value, false_value);
  46. }
  47. const Node value = Operation(OperationCode::UBitwiseOr, NO_PRECISE, values[0], values[1]);
  48. SetRegister(bb, instr.gpr0, value);
  49. return pc;
  50. }
  51. } // namespace VideoCommon::Shader