Merge pull request #2739 from lioncash/cflow
video_core/control_flow: Minor changes/warning cleanup
This commit is contained in:
commit
b0ff3179ef
4 changed files with 53 additions and 33 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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)};
|
||||||
|
|
Loading…
Reference in a new issue