half_set.cpp 2.3 KB

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