control_flow.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <list>
  6. #include <optional>
  7. #include <set>
  8. #include <variant>
  9. #include "video_core/engines/shader_bytecode.h"
  10. #include "video_core/shader/ast.h"
  11. #include "video_core/shader/compiler_settings.h"
  12. #include "video_core/shader/registry.h"
  13. #include "video_core/shader/shader_ir.h"
  14. namespace VideoCommon::Shader {
  15. using Tegra::Shader::ConditionCode;
  16. using Tegra::Shader::Pred;
  17. constexpr s32 exit_branch = -1;
  18. struct Condition {
  19. Pred predicate{Pred::UnusedIndex};
  20. ConditionCode cc{ConditionCode::T};
  21. bool IsUnconditional() const {
  22. return predicate == Pred::UnusedIndex && cc == ConditionCode::T;
  23. }
  24. bool operator==(const Condition& other) const {
  25. return std::tie(predicate, cc) == std::tie(other.predicate, other.cc);
  26. }
  27. bool operator!=(const Condition& other) const {
  28. return !operator==(other);
  29. }
  30. };
  31. class SingleBranch {
  32. public:
  33. SingleBranch() = default;
  34. SingleBranch(Condition condition, s32 address, bool kill, bool is_sync, bool is_brk,
  35. bool ignore)
  36. : condition{condition}, address{address}, kill{kill}, is_sync{is_sync}, is_brk{is_brk},
  37. ignore{ignore} {}
  38. bool operator==(const SingleBranch& b) const {
  39. return std::tie(condition, address, kill, is_sync, is_brk, ignore) ==
  40. std::tie(b.condition, b.address, b.kill, b.is_sync, b.is_brk, b.ignore);
  41. }
  42. bool operator!=(const SingleBranch& b) const {
  43. return !operator==(b);
  44. }
  45. Condition condition{};
  46. s32 address{exit_branch};
  47. bool kill{};
  48. bool is_sync{};
  49. bool is_brk{};
  50. bool ignore{};
  51. };
  52. struct CaseBranch {
  53. CaseBranch(u32 cmp_value, u32 address) : cmp_value{cmp_value}, address{address} {}
  54. u32 cmp_value;
  55. u32 address;
  56. };
  57. class MultiBranch {
  58. public:
  59. MultiBranch(u32 gpr, std::vector<CaseBranch>&& branches)
  60. : gpr{gpr}, branches{std::move(branches)} {}
  61. u32 gpr{};
  62. std::vector<CaseBranch> branches{};
  63. };
  64. using BranchData = std::variant<SingleBranch, MultiBranch>;
  65. using BlockBranchInfo = std::shared_ptr<BranchData>;
  66. bool BlockBranchInfoAreEqual(BlockBranchInfo first, BlockBranchInfo second);
  67. struct ShaderBlock {
  68. u32 start{};
  69. u32 end{};
  70. bool ignore_branch{};
  71. BlockBranchInfo branch{};
  72. bool operator==(const ShaderBlock& sb) const {
  73. return std::tie(start, end, ignore_branch) ==
  74. std::tie(sb.start, sb.end, sb.ignore_branch) &&
  75. BlockBranchInfoAreEqual(branch, sb.branch);
  76. }
  77. bool operator!=(const ShaderBlock& sb) const {
  78. return !operator==(sb);
  79. }
  80. };
  81. struct ShaderCharacteristics {
  82. std::list<ShaderBlock> blocks{};
  83. std::set<u32> labels{};
  84. u32 start{};
  85. u32 end{};
  86. ASTManager manager{true, true};
  87. CompilerSettings settings{};
  88. };
  89. std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 start_address,
  90. const CompilerSettings& settings,
  91. Registry& registry);
  92. } // namespace VideoCommon::Shader