mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-12-13 15:19:11 +00:00
* shader_recompiler: Remove remnants of old discard Also constant propagate conditional discard if condition is constant * resource_tracking_pass: Rework sharp tracking for robustness * resource_tracking_pass: Add source dominance analysis When reachability is not enough to prune source list, check if a source dominates all other sources * resource_tracking_pass: Fix immediate check How did this work before * resource_tracking_pass: Remove unused template type * readlane_elimination_pass: Don't add phi when all args are the same New sharp tracking exposed some bad sources coming on sampler sharps with aniso disable pattern that also were part of readlane pattern, fix tracking by removing the unnecessary phis inbetween * resource_tracking_pass: Allow phi in disable aniso pattern * resource_tracking_pass: Handle not valid buffer sharp and more phi in aniso pattern
87 lines
2.2 KiB
C++
87 lines
2.2 KiB
C++
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <span>
|
|
#include <string>
|
|
#include <boost/container/small_vector.hpp>
|
|
#include <boost/intrusive/set.hpp>
|
|
|
|
#include "common/assert.h"
|
|
#include "common/object_pool.h"
|
|
#include "common/types.h"
|
|
#include "shader_recompiler/frontend/instruction.h"
|
|
#include "shader_recompiler/ir/condition.h"
|
|
|
|
namespace Shader::Gcn {
|
|
|
|
using Hook =
|
|
boost::intrusive::set_base_hook<boost::intrusive::link_mode<boost::intrusive::normal_link>>;
|
|
|
|
enum class EndClass {
|
|
Branch, ///< Block ends with a (un)conditional branch.
|
|
Exit, ///< Block ends with an exit instruction.
|
|
};
|
|
|
|
/// A block represents a linear range of instructions.
|
|
struct Block : Hook {
|
|
[[nodiscard]] bool Contains(u32 pc) const noexcept;
|
|
|
|
bool operator<(const Block& rhs) const noexcept {
|
|
return begin < rhs.begin;
|
|
}
|
|
|
|
u32 begin;
|
|
u32 end;
|
|
u32 begin_index;
|
|
u32 end_index;
|
|
IR::Condition cond{};
|
|
GcnInst end_inst{};
|
|
EndClass end_class{};
|
|
Block* branch_true{};
|
|
Block* branch_false{};
|
|
bool is_dummy{};
|
|
};
|
|
|
|
class CFG {
|
|
using Label = u32;
|
|
|
|
public:
|
|
explicit CFG(Common::ObjectPool<Block>& block_pool, std::span<const GcnInst> inst_list);
|
|
|
|
[[nodiscard]] std::string Dot() const;
|
|
|
|
private:
|
|
void EmitLabels();
|
|
void EmitBlocks();
|
|
void LinkBlocks();
|
|
void SplitDivergenceScopes();
|
|
|
|
void AddLabel(Label address) {
|
|
const auto it = std::ranges::find(labels, address);
|
|
if (it == labels.end()) {
|
|
labels.push_back(address);
|
|
}
|
|
};
|
|
|
|
size_t GetIndex(Label label) {
|
|
if (label == 0) {
|
|
return 0ULL;
|
|
}
|
|
const auto it_index = std::ranges::lower_bound(index_to_pc, label);
|
|
ASSERT(it_index != index_to_pc.end() || label > index_to_pc.back());
|
|
return std::distance(index_to_pc.begin(), it_index);
|
|
};
|
|
|
|
public:
|
|
Common::ObjectPool<Block>& block_pool;
|
|
std::span<const GcnInst> inst_list;
|
|
std::vector<u32> index_to_pc;
|
|
boost::container::small_vector<Label, 16> labels;
|
|
boost::intrusive::set<Block> blocks;
|
|
};
|
|
|
|
} // namespace Shader::Gcn
|