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