shader_ir: Declare Manager and pass it to appropiate programs.
This commit is contained in:
parent
8be6e1c522
commit
6fdd501113
7 changed files with 214 additions and 104 deletions
|
@ -363,6 +363,71 @@ std::string ASTManager::Print() {
|
||||||
return printer.GetResult();
|
return printer.GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTManager::ASTManager() = default;
|
||||||
|
|
||||||
|
ASTManager::~ASTManager() {
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTManager::Init() {
|
||||||
|
main_node = ASTBase::Make<ASTProgram>(ASTNode{});
|
||||||
|
program = std::get_if<ASTProgram>(main_node->GetInnerData());
|
||||||
|
true_condition = MakeExpr<ExprBoolean>(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTManager::ASTManager(ASTManager&& other)
|
||||||
|
: labels_map(std::move(other.labels_map)), labels_count{other.labels_count},
|
||||||
|
gotos(std::move(other.gotos)), labels(std::move(other.labels)), variables{other.variables},
|
||||||
|
program{other.program}, main_node{other.main_node}, true_condition{other.true_condition} {
|
||||||
|
other.main_node.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTManager& ASTManager::operator=(ASTManager&& other) {
|
||||||
|
labels_map = std::move(other.labels_map);
|
||||||
|
labels_count = other.labels_count;
|
||||||
|
gotos = std::move(other.gotos);
|
||||||
|
labels = std::move(other.labels);
|
||||||
|
variables = other.variables;
|
||||||
|
program = other.program;
|
||||||
|
main_node = other.main_node;
|
||||||
|
true_condition = other.true_condition;
|
||||||
|
|
||||||
|
other.main_node.reset();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTManager::DeclareLabel(u32 address) {
|
||||||
|
const auto pair = labels_map.emplace(address, labels_count);
|
||||||
|
if (pair.second) {
|
||||||
|
labels_count++;
|
||||||
|
labels.resize(labels_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTManager::InsertLabel(u32 address) {
|
||||||
|
u32 index = labels_map[address];
|
||||||
|
ASTNode label = ASTBase::Make<ASTLabel>(main_node, index);
|
||||||
|
labels[index] = label;
|
||||||
|
program->nodes.PushBack(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTManager::InsertGoto(Expr condition, u32 address) {
|
||||||
|
u32 index = labels_map[address];
|
||||||
|
ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index);
|
||||||
|
gotos.push_back(goto_node);
|
||||||
|
program->nodes.PushBack(goto_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTManager::InsertBlock(u32 start_address, u32 end_address) {
|
||||||
|
ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address);
|
||||||
|
program->nodes.PushBack(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASTManager::InsertReturn(Expr condition, bool kills) {
|
||||||
|
ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills);
|
||||||
|
program->nodes.PushBack(node);
|
||||||
|
}
|
||||||
|
|
||||||
void ASTManager::Decompile() {
|
void ASTManager::Decompile() {
|
||||||
auto it = gotos.begin();
|
auto it = gotos.begin();
|
||||||
while (it != gotos.end()) {
|
while (it != gotos.end()) {
|
||||||
|
@ -460,7 +525,6 @@ void ASTManager::SanityCheck() {
|
||||||
|
|
||||||
void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) {
|
void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) {
|
||||||
// ShowCurrentState("Before DoWhile Enclose");
|
// ShowCurrentState("Before DoWhile Enclose");
|
||||||
enclose_count++;
|
|
||||||
ASTZipper& zipper = goto_node->GetManager();
|
ASTZipper& zipper = goto_node->GetManager();
|
||||||
ASTNode loop_start = label->GetNext();
|
ASTNode loop_start = label->GetNext();
|
||||||
if (loop_start == goto_node) {
|
if (loop_start == goto_node) {
|
||||||
|
@ -481,7 +545,6 @@ void ASTManager::EncloseDoWhile(ASTNode goto_node, ASTNode label) {
|
||||||
|
|
||||||
void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) {
|
void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) {
|
||||||
// ShowCurrentState("Before IfThen Enclose");
|
// ShowCurrentState("Before IfThen Enclose");
|
||||||
enclose_count++;
|
|
||||||
ASTZipper& zipper = goto_node->GetManager();
|
ASTZipper& zipper = goto_node->GetManager();
|
||||||
ASTNode if_end = label->GetPrevious();
|
ASTNode if_end = label->GetPrevious();
|
||||||
if (if_end == goto_node) {
|
if (if_end == goto_node) {
|
||||||
|
@ -514,7 +577,6 @@ void ASTManager::EncloseIfThen(ASTNode goto_node, ASTNode label) {
|
||||||
|
|
||||||
void ASTManager::MoveOutward(ASTNode goto_node) {
|
void ASTManager::MoveOutward(ASTNode goto_node) {
|
||||||
// ShowCurrentState("Before MoveOutward");
|
// ShowCurrentState("Before MoveOutward");
|
||||||
outward_count++;
|
|
||||||
ASTZipper& zipper = goto_node->GetManager();
|
ASTZipper& zipper = goto_node->GetManager();
|
||||||
ASTNode parent = goto_node->GetParent();
|
ASTNode parent = goto_node->GetParent();
|
||||||
ASTZipper& zipper2 = parent->GetManager();
|
ASTZipper& zipper2 = parent->GetManager();
|
||||||
|
@ -582,4 +644,75 @@ void ASTManager::MoveOutward(ASTNode goto_node) {
|
||||||
// ShowCurrentState("After MoveOutward");
|
// ShowCurrentState("After MoveOutward");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ASTClearer {
|
||||||
|
public:
|
||||||
|
ASTClearer() = default;
|
||||||
|
|
||||||
|
void operator()(ASTProgram& ast) {
|
||||||
|
ASTNode current = ast.nodes.GetFirst();
|
||||||
|
while (current) {
|
||||||
|
Visit(current);
|
||||||
|
current = current->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(ASTIfThen& ast) {
|
||||||
|
ASTNode current = ast.nodes.GetFirst();
|
||||||
|
while (current) {
|
||||||
|
Visit(current);
|
||||||
|
current = current->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(ASTIfElse& ast) {
|
||||||
|
ASTNode current = ast.nodes.GetFirst();
|
||||||
|
while (current) {
|
||||||
|
Visit(current);
|
||||||
|
current = current->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(ASTBlockEncoded& ast) {}
|
||||||
|
|
||||||
|
void operator()(ASTBlockDecoded& ast) {
|
||||||
|
ast.nodes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(ASTVarSet& ast) {}
|
||||||
|
|
||||||
|
void operator()(ASTLabel& ast) {}
|
||||||
|
|
||||||
|
void operator()(ASTGoto& ast) {}
|
||||||
|
|
||||||
|
void operator()(ASTDoWhile& ast) {
|
||||||
|
ASTNode current = ast.nodes.GetFirst();
|
||||||
|
while (current) {
|
||||||
|
Visit(current);
|
||||||
|
current = current->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator()(ASTReturn& ast) {}
|
||||||
|
|
||||||
|
void operator()(ASTBreak& ast) {}
|
||||||
|
|
||||||
|
void Visit(ASTNode& node) {
|
||||||
|
std::visit(*this, *node->GetInnerData());
|
||||||
|
node->Clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void ASTManager::Clear() {
|
||||||
|
if (!main_node) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ASTClearer clearer{};
|
||||||
|
clearer.Visit(main_node);
|
||||||
|
main_node.reset();
|
||||||
|
program = nullptr;
|
||||||
|
labels_map.clear();
|
||||||
|
labels.clear();
|
||||||
|
gotos.clear();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace VideoCommon::Shader
|
} // namespace VideoCommon::Shader
|
||||||
|
|
|
@ -30,8 +30,8 @@ class ASTDoWhile;
|
||||||
class ASTReturn;
|
class ASTReturn;
|
||||||
class ASTBreak;
|
class ASTBreak;
|
||||||
|
|
||||||
using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded, ASTVarSet, ASTGoto,
|
using ASTData = std::variant<ASTProgram, ASTIfThen, ASTIfElse, ASTBlockEncoded, ASTBlockDecoded,
|
||||||
ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>;
|
ASTVarSet, ASTGoto, ASTLabel, ASTDoWhile, ASTReturn, ASTBreak>;
|
||||||
|
|
||||||
using ASTNode = std::shared_ptr<ASTBase>;
|
using ASTNode = std::shared_ptr<ASTBase>;
|
||||||
|
|
||||||
|
@ -261,6 +261,13 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
next.reset();
|
||||||
|
previous.reset();
|
||||||
|
parent.reset();
|
||||||
|
manager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ASTZipper;
|
friend class ASTZipper;
|
||||||
|
|
||||||
|
@ -273,43 +280,26 @@ private:
|
||||||
|
|
||||||
class ASTManager final {
|
class ASTManager final {
|
||||||
public:
|
public:
|
||||||
explicit ASTManager() {
|
ASTManager();
|
||||||
main_node = ASTBase::Make<ASTProgram>(ASTNode{});
|
~ASTManager();
|
||||||
program = std::get_if<ASTProgram>(main_node->GetInnerData());
|
|
||||||
true_condition = MakeExpr<ExprBoolean>(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeclareLabel(u32 address) {
|
ASTManager(const ASTManager& o) = delete;
|
||||||
const auto pair = labels_map.emplace(address, labels_count);
|
ASTManager& operator=(const ASTManager& other) = delete;
|
||||||
if (pair.second) {
|
|
||||||
labels_count++;
|
|
||||||
labels.resize(labels_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InsertLabel(u32 address) {
|
ASTManager(ASTManager&& other);
|
||||||
u32 index = labels_map[address];
|
ASTManager& operator=(ASTManager&& other);
|
||||||
ASTNode label = ASTBase::Make<ASTLabel>(main_node, index);
|
|
||||||
labels[index] = label;
|
|
||||||
program->nodes.PushBack(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InsertGoto(Expr condition, u32 address) {
|
void Init();
|
||||||
u32 index = labels_map[address];
|
|
||||||
ASTNode goto_node = ASTBase::Make<ASTGoto>(main_node, condition, index);
|
|
||||||
gotos.push_back(goto_node);
|
|
||||||
program->nodes.PushBack(goto_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InsertBlock(u32 start_address, u32 end_address) {
|
void DeclareLabel(u32 address);
|
||||||
ASTNode block = ASTBase::Make<ASTBlockEncoded>(main_node, start_address, end_address);
|
|
||||||
program->nodes.PushBack(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
void InsertReturn(Expr condition, bool kills) {
|
void InsertLabel(u32 address);
|
||||||
ASTNode node = ASTBase::Make<ASTReturn>(main_node, condition, kills);
|
|
||||||
program->nodes.PushBack(node);
|
void InsertGoto(Expr condition, u32 address);
|
||||||
}
|
|
||||||
|
void InsertBlock(u32 start_address, u32 end_address);
|
||||||
|
|
||||||
|
void InsertReturn(Expr condition, bool kills);
|
||||||
|
|
||||||
std::string Print();
|
std::string Print();
|
||||||
|
|
||||||
|
@ -323,6 +313,12 @@ public:
|
||||||
return gotos.size() == 0;
|
return gotos.size() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASTNode GetProgram() {
|
||||||
|
return main_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool IndirectlyRelated(ASTNode first, ASTNode second);
|
bool IndirectlyRelated(ASTNode first, ASTNode second);
|
||||||
|
|
||||||
|
@ -332,7 +328,7 @@ private:
|
||||||
|
|
||||||
void EncloseIfThen(ASTNode goto_node, ASTNode label);
|
void EncloseIfThen(ASTNode goto_node, ASTNode label);
|
||||||
|
|
||||||
void MoveOutward(ASTNode goto_node) ;
|
void MoveOutward(ASTNode goto_node);
|
||||||
|
|
||||||
u32 NewVariable() {
|
u32 NewVariable() {
|
||||||
u32 new_var = variables;
|
u32 new_var = variables;
|
||||||
|
@ -345,11 +341,9 @@ private:
|
||||||
std::vector<ASTNode> labels{};
|
std::vector<ASTNode> labels{};
|
||||||
std::list<ASTNode> gotos{};
|
std::list<ASTNode> gotos{};
|
||||||
u32 variables{};
|
u32 variables{};
|
||||||
ASTProgram* program;
|
ASTProgram* program{};
|
||||||
ASTNode main_node;
|
ASTNode main_node{};
|
||||||
Expr true_condition;
|
Expr true_condition{};
|
||||||
u32 outward_count{};
|
|
||||||
u32 enclose_count{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCommon::Shader
|
} // namespace VideoCommon::Shader
|
||||||
|
|
|
@ -57,8 +57,8 @@ struct BlockInfo {
|
||||||
|
|
||||||
struct CFGRebuildState {
|
struct CFGRebuildState {
|
||||||
explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size,
|
explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size,
|
||||||
const u32 start)
|
const u32 start, ASTManager& manager)
|
||||||
: start{start}, program_code{program_code}, program_size{program_size} {}
|
: program_code{program_code}, program_size{program_size}, start{start}, manager{manager} {}
|
||||||
|
|
||||||
u32 start{};
|
u32 start{};
|
||||||
std::vector<BlockInfo> block_info{};
|
std::vector<BlockInfo> block_info{};
|
||||||
|
@ -71,6 +71,7 @@ struct CFGRebuildState {
|
||||||
std::unordered_map<u32, BlockStack> stacks{};
|
std::unordered_map<u32, BlockStack> stacks{};
|
||||||
const ProgramCode& program_code;
|
const ProgramCode& program_code;
|
||||||
const std::size_t program_size;
|
const std::size_t program_size;
|
||||||
|
ASTManager& manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BlockCollision : u32 { None, Found, Inside };
|
enum class BlockCollision : u32 { None, Found, Inside };
|
||||||
|
@ -455,29 +456,28 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompileShader(CFGRebuildState& state) {
|
void DecompileShader(CFGRebuildState& state) {
|
||||||
ASTManager manager{};
|
state.manager.Init();
|
||||||
for (auto label : state.labels) {
|
for (auto label : state.labels) {
|
||||||
manager.DeclareLabel(label);
|
state.manager.DeclareLabel(label);
|
||||||
}
|
}
|
||||||
for (auto& block : state.block_info) {
|
for (auto& block : state.block_info) {
|
||||||
if (state.labels.count(block.start) != 0) {
|
if (state.labels.count(block.start) != 0) {
|
||||||
manager.InsertLabel(block.start);
|
state.manager.InsertLabel(block.start);
|
||||||
}
|
}
|
||||||
u32 end = block.branch.ignore ? block.end + 1 : block.end;
|
u32 end = block.branch.ignore ? block.end + 1 : block.end;
|
||||||
manager.InsertBlock(block.start, end);
|
state.manager.InsertBlock(block.start, end);
|
||||||
if (!block.branch.ignore) {
|
if (!block.branch.ignore) {
|
||||||
InsertBranch(manager, block.branch);
|
InsertBranch(state.manager, block.branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//manager.ShowCurrentState("Before Decompiling");
|
// state.manager.ShowCurrentState("Before Decompiling");
|
||||||
manager.Decompile();
|
state.manager.Decompile();
|
||||||
//manager.ShowCurrentState("After Decompiling");
|
// state.manager.ShowCurrentState("After Decompiling");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
|
std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
|
||||||
std::size_t program_size, u32 start_address) {
|
u32 start_address, ASTManager& manager) {
|
||||||
CFGRebuildState state{program_code, program_size, start_address};
|
CFGRebuildState state{program_code, program_size, start_address, manager};
|
||||||
|
|
||||||
// Inspect Code and generate blocks
|
// Inspect Code and generate blocks
|
||||||
state.labels.clear();
|
state.labels.clear();
|
||||||
state.labels.emplace(start_address);
|
state.labels.emplace(start_address);
|
||||||
|
@ -503,12 +503,21 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
|
||||||
[](const BlockInfo& a, const BlockInfo& b) -> bool { return a.start < b.start; });
|
[](const BlockInfo& a, const BlockInfo& b) -> bool { return a.start < b.start; });
|
||||||
if (decompiled) {
|
if (decompiled) {
|
||||||
DecompileShader(state);
|
DecompileShader(state);
|
||||||
|
decompiled = state.manager.IsFullyDecompiled();
|
||||||
|
if (!decompiled) {
|
||||||
|
LOG_CRITICAL(HW_GPU, "Failed to remove all the gotos!:");
|
||||||
|
state.manager.ShowCurrentState("Of Shader");
|
||||||
|
state.manager.Clear();
|
||||||
}
|
}
|
||||||
ShaderCharacteristics result_out{};
|
}
|
||||||
result_out.decompilable = decompiled;
|
auto result_out = std::make_unique<ShaderCharacteristics>();
|
||||||
result_out.start = start_address;
|
result_out->decompiled = decompiled;
|
||||||
result_out.end = start_address;
|
result_out->start = start_address;
|
||||||
for (const auto& block : state.block_info) {
|
if (decompiled) {
|
||||||
|
result_out->end = state.block_info.back().end + 1;
|
||||||
|
return std::move(result_out);
|
||||||
|
}
|
||||||
|
for (auto& block : state.block_info) {
|
||||||
ShaderBlock new_block{};
|
ShaderBlock new_block{};
|
||||||
new_block.start = block.start;
|
new_block.start = block.start;
|
||||||
new_block.end = block.end;
|
new_block.end = block.end;
|
||||||
|
@ -518,26 +527,20 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
|
||||||
new_block.branch.kills = block.branch.kill;
|
new_block.branch.kills = block.branch.kill;
|
||||||
new_block.branch.address = block.branch.address;
|
new_block.branch.address = block.branch.address;
|
||||||
}
|
}
|
||||||
result_out.end = std::max(result_out.end, block.end);
|
result_out->end = std::max(result_out->end, block.end);
|
||||||
result_out.blocks.push_back(new_block);
|
result_out->blocks.push_back(new_block);
|
||||||
}
|
}
|
||||||
if (result_out.decompilable) {
|
auto back = result_out->blocks.begin();
|
||||||
result_out.labels = std::move(state.labels);
|
|
||||||
return {std::move(result_out)};
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's not decompilable, merge the unlabelled blocks together
|
|
||||||
auto back = result_out.blocks.begin();
|
|
||||||
auto next = std::next(back);
|
auto next = std::next(back);
|
||||||
while (next != result_out.blocks.end()) {
|
while (next != result_out->blocks.end()) {
|
||||||
if (state.labels.count(next->start) == 0 && next->start == back->end + 1) {
|
if (state.labels.count(next->start) == 0 && next->start == back->end + 1) {
|
||||||
back->end = next->end;
|
back->end = next->end;
|
||||||
next = result_out.blocks.erase(next);
|
next = result_out->blocks.erase(next);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
back = next;
|
back = next;
|
||||||
++next;
|
++next;
|
||||||
}
|
}
|
||||||
return {std::move(result_out)};
|
return std::move(result_out);
|
||||||
}
|
}
|
||||||
} // namespace VideoCommon::Shader
|
} // namespace VideoCommon::Shader
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "video_core/engines/shader_bytecode.h"
|
#include "video_core/engines/shader_bytecode.h"
|
||||||
#include "video_core/shader/shader_ir.h"
|
#include "video_core/shader/shader_ir.h"
|
||||||
|
#include "video_core/shader/ast.h"
|
||||||
|
|
||||||
namespace VideoCommon::Shader {
|
namespace VideoCommon::Shader {
|
||||||
|
|
||||||
|
@ -67,13 +68,12 @@ struct ShaderBlock {
|
||||||
|
|
||||||
struct ShaderCharacteristics {
|
struct ShaderCharacteristics {
|
||||||
std::list<ShaderBlock> blocks{};
|
std::list<ShaderBlock> blocks{};
|
||||||
bool decompilable{};
|
bool decompiled{};
|
||||||
u32 start{};
|
u32 start{};
|
||||||
u32 end{};
|
u32 end{};
|
||||||
std::set<u32> labels{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
|
std::unique_ptr<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
|
||||||
std::size_t program_size, u32 start_address);
|
u32 start_address, ASTManager& manager);
|
||||||
|
|
||||||
} // namespace VideoCommon::Shader
|
} // namespace VideoCommon::Shader
|
||||||
|
|
|
@ -39,36 +39,14 @@ void ShaderIR::Decode() {
|
||||||
std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
|
std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
|
||||||
|
|
||||||
disable_flow_stack = false;
|
disable_flow_stack = false;
|
||||||
const auto info = ScanFlow(program_code, program_size, main_offset);
|
const auto info =
|
||||||
|
ScanFlow(program_code, program_size, main_offset, program_manager);
|
||||||
if (info) {
|
if (info) {
|
||||||
const auto& shader_info = *info;
|
const auto& shader_info = *info;
|
||||||
coverage_begin = shader_info.start;
|
coverage_begin = shader_info.start;
|
||||||
coverage_end = shader_info.end;
|
coverage_end = shader_info.end;
|
||||||
if (shader_info.decompilable) {
|
if (shader_info.decompiled) {
|
||||||
disable_flow_stack = true;
|
disable_flow_stack = true;
|
||||||
const auto insert_block = [this](NodeBlock& nodes, u32 label) {
|
|
||||||
if (label == static_cast<u32>(exit_branch)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
basic_blocks.insert({label, nodes});
|
|
||||||
};
|
|
||||||
const auto& blocks = shader_info.blocks;
|
|
||||||
NodeBlock current_block;
|
|
||||||
u32 current_label = static_cast<u32>(exit_branch);
|
|
||||||
for (auto& block : blocks) {
|
|
||||||
if (shader_info.labels.count(block.start) != 0) {
|
|
||||||
insert_block(current_block, current_label);
|
|
||||||
current_block.clear();
|
|
||||||
current_label = block.start;
|
|
||||||
}
|
|
||||||
if (!block.ignore_branch) {
|
|
||||||
DecodeRangeInner(current_block, block.start, block.end);
|
|
||||||
InsertControlFlow(current_block, block);
|
|
||||||
} else {
|
|
||||||
DecodeRangeInner(current_block, block.start, block.end + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
insert_block(current_block, current_label);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method");
|
LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method");
|
||||||
|
|
|
@ -23,7 +23,7 @@ using Tegra::Shader::PredOperation;
|
||||||
using Tegra::Shader::Register;
|
using Tegra::Shader::Register;
|
||||||
|
|
||||||
ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset, const std::size_t size)
|
ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset, const std::size_t size)
|
||||||
: program_code{program_code}, main_offset{main_offset}, program_size{size} {
|
: program_code{program_code}, main_offset{main_offset}, program_size{size}, program_manager{} {
|
||||||
Decode();
|
Decode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "video_core/engines/shader_bytecode.h"
|
#include "video_core/engines/shader_bytecode.h"
|
||||||
#include "video_core/engines/shader_header.h"
|
#include "video_core/engines/shader_header.h"
|
||||||
#include "video_core/shader/node.h"
|
#include "video_core/shader/node.h"
|
||||||
|
#include "video_core/shader/ast.h"
|
||||||
|
|
||||||
namespace VideoCommon::Shader {
|
namespace VideoCommon::Shader {
|
||||||
|
|
||||||
|
@ -364,6 +365,7 @@ private:
|
||||||
|
|
||||||
std::map<u32, NodeBlock> basic_blocks;
|
std::map<u32, NodeBlock> basic_blocks;
|
||||||
NodeBlock global_code;
|
NodeBlock global_code;
|
||||||
|
ASTManager program_manager;
|
||||||
|
|
||||||
std::set<u32> used_registers;
|
std::set<u32> used_registers;
|
||||||
std::set<Tegra::Shader::Pred> used_predicates;
|
std::set<Tegra::Shader::Pred> used_predicates;
|
||||||
|
|
Loading…
Reference in a new issue