mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-11-04 00:49:02 -06:00 
			
		
		
		
	Merge pull request #2739 from lioncash/cflow
video_core/control_flow: Minor changes/warning cleanup
This commit is contained in:
		@@ -15,7 +15,7 @@
 | 
			
		||||
#include "video_core/shader/shader_ir.h"
 | 
			
		||||
 | 
			
		||||
namespace VideoCommon::Shader {
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
using Tegra::Shader::Instruction;
 | 
			
		||||
using Tegra::Shader::OpCode;
 | 
			
		||||
 | 
			
		||||
@@ -29,8 +29,7 @@ struct Query {
 | 
			
		||||
 | 
			
		||||
struct BlockStack {
 | 
			
		||||
    BlockStack() = default;
 | 
			
		||||
    BlockStack(const BlockStack& b) = default;
 | 
			
		||||
    BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {}
 | 
			
		||||
    explicit BlockStack(const Query& q) : ssy_stack{q.ssy_stack}, pbk_stack{q.pbk_stack} {}
 | 
			
		||||
    std::stack<u32> ssy_stack{};
 | 
			
		||||
    std::stack<u32> pbk_stack{};
 | 
			
		||||
};
 | 
			
		||||
@@ -58,7 +57,7 @@ struct BlockInfo {
 | 
			
		||||
struct CFGRebuildState {
 | 
			
		||||
    explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size,
 | 
			
		||||
                             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{};
 | 
			
		||||
    std::vector<BlockInfo> block_info{};
 | 
			
		||||
@@ -85,7 +84,7 @@ std::pair<BlockCollision, u32> TryGetBlock(CFGRebuildState& state, u32 address)
 | 
			
		||||
            return {BlockCollision::Inside, index};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return {BlockCollision::None, -1};
 | 
			
		||||
    return {BlockCollision::None, 0xFFFFFFFF};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ParseInfo {
 | 
			
		||||
@@ -365,27 +364,29 @@ bool TryQuery(CFGRebuildState& state) {
 | 
			
		||||
        const auto gather_end = labels.upper_bound(block.end);
 | 
			
		||||
        while (gather_start != gather_end) {
 | 
			
		||||
            cc.push(gather_start->second);
 | 
			
		||||
            gather_start++;
 | 
			
		||||
            ++gather_start;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    if (state.queries.empty()) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Query& q = state.queries.front();
 | 
			
		||||
    const u32 block_index = state.registered[q.address];
 | 
			
		||||
    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
 | 
			
		||||
    // consumes a label. Schedule new queries accordingly
 | 
			
		||||
    if (block.visited) {
 | 
			
		||||
        BlockStack& stack = state.stacks[q.address];
 | 
			
		||||
        const bool all_okay = (stack.ssy_stack.size() == 0 || q.ssy_stack == stack.ssy_stack) &&
 | 
			
		||||
                              (stack.pbk_stack.size() == 0 || q.pbk_stack == stack.pbk_stack);
 | 
			
		||||
        const bool all_okay = (stack.ssy_stack.empty() || q.ssy_stack == stack.ssy_stack) &&
 | 
			
		||||
                              (stack.pbk_stack.empty() || q.pbk_stack == stack.pbk_stack);
 | 
			
		||||
        state.queries.pop_front();
 | 
			
		||||
        return all_okay;
 | 
			
		||||
    }
 | 
			
		||||
    block.visited = true;
 | 
			
		||||
    state.stacks[q.address] = BlockStack{q};
 | 
			
		||||
    state.stacks.insert_or_assign(q.address, BlockStack{q});
 | 
			
		||||
 | 
			
		||||
    Query q2(q);
 | 
			
		||||
    state.queries.pop_front();
 | 
			
		||||
    gather_labels(q2.ssy_stack, state.ssy_labels, block);
 | 
			
		||||
@@ -394,6 +395,7 @@ bool TryQuery(CFGRebuildState& state) {
 | 
			
		||||
        q2.address = block.end + 1;
 | 
			
		||||
        state.queries.push_back(q2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Query conditional_query{q2};
 | 
			
		||||
    if (block.branch.is_sync) {
 | 
			
		||||
        if (block.branch.address == unassigned_branch) {
 | 
			
		||||
@@ -408,13 +410,15 @@ bool TryQuery(CFGRebuildState& state) {
 | 
			
		||||
        conditional_query.pbk_stack.pop();
 | 
			
		||||
    }
 | 
			
		||||
    conditional_query.address = block.branch.address;
 | 
			
		||||
    state.queries.push_back(conditional_query);
 | 
			
		||||
    state.queries.push_back(std::move(conditional_query));
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
 | 
			
		||||
                                              u32 start_address) {
 | 
			
		||||
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
 | 
			
		||||
                                              std::size_t program_size, u32 start_address) {
 | 
			
		||||
    CFGRebuildState state{program_code, program_size, start_address};
 | 
			
		||||
 | 
			
		||||
    // Inspect Code and generate blocks
 | 
			
		||||
    state.labels.clear();
 | 
			
		||||
    state.labels.emplace(start_address);
 | 
			
		||||
@@ -424,10 +428,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Decompile Stacks
 | 
			
		||||
    Query start_query{};
 | 
			
		||||
    start_query.address = state.start;
 | 
			
		||||
    state.queries.push_back(start_query);
 | 
			
		||||
    state.queries.push_back(Query{state.start, {}, {}});
 | 
			
		||||
    bool decompiled = true;
 | 
			
		||||
    while (!state.queries.empty()) {
 | 
			
		||||
        if (!TryQuery(state)) {
 | 
			
		||||
@@ -435,14 +438,15 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Sort and organize results
 | 
			
		||||
    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{};
 | 
			
		||||
    result_out.decompilable = decompiled;
 | 
			
		||||
    result_out.start = start_address;
 | 
			
		||||
    result_out.end = start_address;
 | 
			
		||||
    for (auto& block : state.block_info) {
 | 
			
		||||
    for (const auto& block : state.block_info) {
 | 
			
		||||
        ShaderBlock new_block{};
 | 
			
		||||
        new_block.start = block.start;
 | 
			
		||||
        new_block.end = block.end;
 | 
			
		||||
@@ -457,8 +461,9 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
 | 
			
		||||
    }
 | 
			
		||||
    if (result_out.decompilable) {
 | 
			
		||||
        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
 | 
			
		||||
    auto back = result_out.blocks.begin();
 | 
			
		||||
    auto next = std::next(back);
 | 
			
		||||
@@ -469,8 +474,8 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        back = next;
 | 
			
		||||
        next++;
 | 
			
		||||
        ++next;
 | 
			
		||||
    }
 | 
			
		||||
    return {result_out};
 | 
			
		||||
    return {std::move(result_out)};
 | 
			
		||||
}
 | 
			
		||||
} // namespace VideoCommon::Shader
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <cstring>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <unordered_set>
 | 
			
		||||
@@ -26,27 +25,44 @@ struct Condition {
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ShaderBlock {
 | 
			
		||||
    u32 start{};
 | 
			
		||||
    u32 end{};
 | 
			
		||||
    bool ignore_branch{};
 | 
			
		||||
    struct Branch {
 | 
			
		||||
        Condition cond{};
 | 
			
		||||
        bool kills{};
 | 
			
		||||
        s32 address{};
 | 
			
		||||
 | 
			
		||||
        bool operator==(const Branch& b) const {
 | 
			
		||||
            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 {
 | 
			
		||||
        return std::tie(start, end, ignore_branch, branch) ==
 | 
			
		||||
               std::tie(sb.start, sb.end, sb.ignore_branch, sb.branch);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool operator!=(const ShaderBlock& sb) const {
 | 
			
		||||
        return !operator==(sb);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ShaderCharacteristics {
 | 
			
		||||
@@ -57,7 +73,7 @@ struct ShaderCharacteristics {
 | 
			
		||||
    std::unordered_set<u32> labels{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
 | 
			
		||||
                                              u32 start_address);
 | 
			
		||||
std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code,
 | 
			
		||||
                                              std::size_t program_size, u32 start_address);
 | 
			
		||||
 | 
			
		||||
} // namespace VideoCommon::Shader
 | 
			
		||||
 
 | 
			
		||||
@@ -47,14 +47,14 @@ void ShaderIR::Decode() {
 | 
			
		||||
        if (shader_info.decompilable) {
 | 
			
		||||
            disable_flow_stack = true;
 | 
			
		||||
            const auto insert_block = [this](NodeBlock& nodes, u32 label) {
 | 
			
		||||
                if (label == exit_branch) {
 | 
			
		||||
                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 = exit_branch;
 | 
			
		||||
            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);
 | 
			
		||||
 
 | 
			
		||||
@@ -24,9 +24,8 @@ StagingCache::StagingCache() = default;
 | 
			
		||||
StagingCache::~StagingCache() = default;
 | 
			
		||||
 | 
			
		||||
SurfaceBaseImpl::SurfaceBaseImpl(GPUVAddr gpu_addr, const SurfaceParams& params)
 | 
			
		||||
    : params{params}, mipmap_sizes(params.num_levels),
 | 
			
		||||
      mipmap_offsets(params.num_levels), gpu_addr{gpu_addr}, host_memory_size{
 | 
			
		||||
                                                                 params.GetHostSizeInBytes()} {
 | 
			
		||||
    : params{params}, host_memory_size{params.GetHostSizeInBytes()}, gpu_addr{gpu_addr},
 | 
			
		||||
      mipmap_sizes(params.num_levels), mipmap_offsets(params.num_levels) {
 | 
			
		||||
    std::size_t offset = 0;
 | 
			
		||||
    for (u32 level = 0; level < params.num_levels; ++level) {
 | 
			
		||||
        const std::size_t mipmap_size{params.GetGuestMipmapSize(level)};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user