3
0
Fork 0
forked from suyu/suyu

Merge pull request #2739 from lioncash/cflow

video_core/control_flow: Minor changes/warning cleanup
This commit is contained in:
bunnei 2019-07-25 13:04:56 -04:00 committed by GitHub
commit b0ff3179ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 33 deletions

View file

@ -15,7 +15,7 @@
#include "video_core/shader/shader_ir.h" #include "video_core/shader/shader_ir.h"
namespace VideoCommon::Shader { namespace VideoCommon::Shader {
namespace {
using Tegra::Shader::Instruction; using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode; using Tegra::Shader::OpCode;
@ -29,8 +29,7 @@ struct Query {
struct BlockStack { struct BlockStack {
BlockStack() = default; BlockStack() = default;
BlockStack(const BlockStack& b) = default; explicit BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {}
BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {}
std::stack<u32> ssy_stack{}; std::stack<u32> ssy_stack{};
std::stack<u32> pbk_stack{}; std::stack<u32> pbk_stack{};
}; };
@ -58,7 +57,7 @@ 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)
: program_code{program_code}, program_size{program_size}, start{start} {} : start{start}, program_code{program_code}, program_size{program_size} {}
u32 start{}; u32 start{};
std::vector<BlockInfo> block_info{}; std::vector<BlockInfo> block_info{};
@ -85,7 +84,7 @@ std::pair<BlockCollision, u32> TryGetBlock(CFGRebuildState& state, u32 address)
return {BlockCollision::Inside, index}; return {BlockCollision::Inside, index};
} }
} }
return {BlockCollision::None, -1}; return {BlockCollision::None, 0xFFFFFFFF};
} }
struct ParseInfo { struct ParseInfo {
@ -365,27 +364,29 @@ bool TryQuery(CFGRebuildState& state) {
const auto gather_end = labels.upper_bound(block.end); const auto gather_end = labels.upper_bound(block.end);
while (gather_start != gather_end) { while (gather_start != gather_end) {
cc.push(gather_start->second); cc.push(gather_start->second);
gather_start++; ++gather_start;
} }
}; };
if (state.queries.empty()) { if (state.queries.empty()) {
return false; return false;
} }
Query& q = state.queries.front(); Query& q = state.queries.front();
const u32 block_index = state.registered[q.address]; const u32 block_index = state.registered[q.address];
BlockInfo& block = state.block_info[block_index]; BlockInfo& block = state.block_info[block_index];
// If the block is visted, check if the stacks match, else gather the ssy/pbk // If the block is visited, check if the stacks match, else gather the ssy/pbk
// labels into the current stack and look if the branch at the end of the block // labels into the current stack and look if the branch at the end of the block
// consumes a label. Schedule new queries accordingly // consumes a label. Schedule new queries accordingly
if (block.visited) { if (block.visited) {
BlockStack& stack = state.stacks[q.address]; BlockStack& stack = state.stacks[q.address];
const bool all_okay = (stack.ssy_stack.size() == 0 || q.ssy_stack == stack.ssy_stack) && const bool all_okay = (stack.ssy_stack.empty() || q.ssy_stack == stack.ssy_stack) &&
(stack.pbk_stack.size() == 0 || q.pbk_stack == stack.pbk_stack); (stack.pbk_stack.empty() || q.pbk_stack == stack.pbk_stack);
state.queries.pop_front(); state.queries.pop_front();
return all_okay; return all_okay;
} }
block.visited = true; block.visited = true;
state.stacks[q.address] = BlockStack{q}; state.stacks.insert_or_assign(q.address, BlockStack{q});
Query q2(q); Query q2(q);
state.queries.pop_front(); state.queries.pop_front();
gather_labels(q2.ssy_stack, state.ssy_labels, block); gather_labels(q2.ssy_stack, state.ssy_labels, block);
@ -394,6 +395,7 @@ bool TryQuery(CFGRebuildState& state) {
q2.address = block.end + 1; q2.address = block.end + 1;
state.queries.push_back(q2); state.queries.push_back(q2);
} }
Query conditional_query{q2}; Query conditional_query{q2};
if (block.branch.is_sync) { if (block.branch.is_sync) {
if (block.branch.address == unassigned_branch) { if (block.branch.address == unassigned_branch) {
@ -408,13 +410,15 @@ bool TryQuery(CFGRebuildState& state) {
conditional_query.pbk_stack.pop(); conditional_query.pbk_stack.pop();
} }
conditional_query.address = block.branch.address; conditional_query.address = block.branch.address;
state.queries.push_back(conditional_query); state.queries.push_back(std::move(conditional_query));
return true; return true;
} }
} // Anonymous namespace
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size, std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
u32 start_address) { std::size_t program_size, u32 start_address) {
CFGRebuildState state{program_code, program_size, start_address}; CFGRebuildState state{program_code, program_size, start_address};
// 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);
@ -424,10 +428,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
return {}; return {};
} }
} }
// Decompile Stacks // Decompile Stacks
Query start_query{}; state.queries.push_back(Query{state.start, {}, {}});
start_query.address = state.start;
state.queries.push_back(start_query);
bool decompiled = true; bool decompiled = true;
while (!state.queries.empty()) { while (!state.queries.empty()) {
if (!TryQuery(state)) { if (!TryQuery(state)) {
@ -435,14 +438,15 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
break; break;
} }
} }
// Sort and organize results // Sort and organize results
std::sort(state.block_info.begin(), state.block_info.end(), std::sort(state.block_info.begin(), state.block_info.end(),
[](const BlockInfo& a, const BlockInfo& b) -> bool { return a.start < b.start; }); [](const BlockInfo& a, const BlockInfo& b) { return a.start < b.start; });
ShaderCharacteristics result_out{}; ShaderCharacteristics result_out{};
result_out.decompilable = decompiled; result_out.decompilable = decompiled;
result_out.start = start_address; result_out.start = start_address;
result_out.end = start_address; result_out.end = start_address;
for (auto& block : state.block_info) { for (const 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;
@ -457,8 +461,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
} }
if (result_out.decompilable) { if (result_out.decompilable) {
result_out.labels = std::move(state.labels); result_out.labels = std::move(state.labels);
return {result_out}; return {std::move(result_out)};
} }
// If it's not decompilable, merge the unlabelled blocks together // If it's not decompilable, merge the unlabelled blocks together
auto back = result_out.blocks.begin(); auto back = result_out.blocks.begin();
auto next = std::next(back); auto next = std::next(back);
@ -469,8 +474,8 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
continue; continue;
} }
back = next; back = next;
next++; ++next;
} }
return {result_out}; return {std::move(result_out)};
} }
} // namespace VideoCommon::Shader } // namespace VideoCommon::Shader

View file

@ -4,7 +4,6 @@
#pragma once #pragma once
#include <cstring>
#include <list> #include <list>
#include <optional> #include <optional>
#include <unordered_set> #include <unordered_set>
@ -26,27 +25,44 @@ struct Condition {
bool IsUnconditional() const { bool IsUnconditional() const {
return predicate == Pred::UnusedIndex && cc == ConditionCode::T; return predicate == Pred::UnusedIndex && cc == ConditionCode::T;
} }
bool operator==(const Condition& other) const { bool operator==(const Condition& other) const {
return std::tie(predicate, cc) == std::tie(other.predicate, other.cc); return std::tie(predicate, cc) == std::tie(other.predicate, other.cc);
} }
bool operator!=(const Condition& other) const {
return !operator==(other);
}
}; };
struct ShaderBlock { struct ShaderBlock {
u32 start{};
u32 end{};
bool ignore_branch{};
struct Branch { struct Branch {
Condition cond{}; Condition cond{};
bool kills{}; bool kills{};
s32 address{}; s32 address{};
bool operator==(const Branch& b) const { bool operator==(const Branch& b) const {
return std::tie(cond, kills, address) == std::tie(b.cond, b.kills, b.address); return std::tie(cond, kills, address) == std::tie(b.cond, b.kills, b.address);
} }
} branch{};
bool operator!=(const Branch& b) const {
return !operator==(b);
}
};
u32 start{};
u32 end{};
bool ignore_branch{};
Branch branch{};
bool operator==(const ShaderBlock& sb) const { bool operator==(const ShaderBlock& sb) const {
return std::tie(start, end, ignore_branch, branch) == return std::tie(start, end, ignore_branch, branch) ==
std::tie(sb.start, sb.end, sb.ignore_branch, sb.branch); std::tie(sb.start, sb.end, sb.ignore_branch, sb.branch);
} }
bool operator!=(const ShaderBlock& sb) const {
return !operator==(sb);
}
}; };
struct ShaderCharacteristics { struct ShaderCharacteristics {
@ -57,7 +73,7 @@ struct ShaderCharacteristics {
std::unordered_set<u32> labels{}; std::unordered_set<u32> labels{};
}; };
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size, std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
u32 start_address); std::size_t program_size, u32 start_address);
} // namespace VideoCommon::Shader } // namespace VideoCommon::Shader

View file

@ -47,14 +47,14 @@ void ShaderIR::Decode() {
if (shader_info.decompilable) { if (shader_info.decompilable) {
disable_flow_stack = true; disable_flow_stack = true;
const auto insert_block = [this](NodeBlock& nodes, u32 label) { const auto insert_block = [this](NodeBlock& nodes, u32 label) {
if (label == exit_branch) { if (label == static_cast<u32>(exit_branch)) {
return; return;
} }
basic_blocks.insert({label, nodes}); basic_blocks.insert({label, nodes});
}; };
const auto& blocks = shader_info.blocks; const auto& blocks = shader_info.blocks;
NodeBlock current_block; NodeBlock current_block;
u32 current_label = exit_branch; u32 current_label = static_cast<u32>(exit_branch);
for (auto& block : blocks) { for (auto& block : blocks) {
if (shader_info.labels.count(block.start) != 0) { if (shader_info.labels.count(block.start) != 0) {
insert_block(current_block, current_label); insert_block(current_block, current_label);

View file

@ -24,9 +24,8 @@ StagingCache::StagingCache() = default;
StagingCache::~StagingCache() = default; StagingCache::~StagingCache() = default;
SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params) SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params)
: params{params}, mipmap_sizes(params.num_levels), : params{params}, host_memory_size{params.GetHostSizeInBytes()}, gpu_addr{gpu_addr},
mipmap_offsets(params.num_levels), gpu_addr{gpu_addr}, host_memory_size{ mipmap_sizes(params.num_levels), mipmap_offsets(params.num_levels) {
params.GetHostSizeInBytes()} {
std::size_t offset = 0; std::size_t offset = 0;
for (u32 level = 0; level < params.num_levels; ++level) { for (u32 level = 0; level < params.num_levels; ++level) {
const std::size_t mipmap_size{params.GetGuestMipmapSize(level)}; const std::size_t mipmap_size{params.GetGuestMipmapSize(level)};