mirror of https://git.suyu.dev/suyu/suyu
Shader_IR: Address Feedback.
This commit is contained in:
parent
e3afd6595a
commit
be856a38d6
|
@ -72,7 +72,7 @@ struct HashableStruct {
|
||||||
|
|
||||||
struct PairHash {
|
struct PairHash {
|
||||||
template <class T1, class T2>
|
template <class T1, class T2>
|
||||||
std::size_t operator()(const std::pair<T1, T2>& pair) const {
|
std::size_t operator()(const std::pair<T1, T2>& pair) const noexcept {
|
||||||
std::size_t seed = std::hash<T1>()(pair.first);
|
std::size_t seed = std::hash<T1>()(pair.first);
|
||||||
boost::hash_combine(seed, std::hash<T2>()(pair.second));
|
boost::hash_combine(seed, std::hash<T2>()(pair.second));
|
||||||
return seed;
|
return seed;
|
||||||
|
|
|
@ -34,6 +34,10 @@ struct SamplerDescriptor {
|
||||||
return raw == rhs.raw;
|
return raw == rhs.raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!=(const SamplerDescriptor& rhs) const noexcept {
|
||||||
|
return !operator==(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
static SamplerDescriptor FromTicTexture(Tegra::Texture::TextureType tic_texture_type) {
|
static SamplerDescriptor FromTicTexture(Tegra::Texture::TextureType tic_texture_type) {
|
||||||
SamplerDescriptor result;
|
SamplerDescriptor result;
|
||||||
switch (tic_texture_type) {
|
switch (tic_texture_type) {
|
||||||
|
@ -73,13 +77,12 @@ struct SamplerDescriptor {
|
||||||
result.is_buffer.Assign(0);
|
result.is_buffer.Assign(0);
|
||||||
result.is_shadow.Assign(0);
|
result.is_shadow.Assign(0);
|
||||||
return result;
|
return result;
|
||||||
case Tegra::Texture::TextureType::Texture1DBuffer: {
|
case Tegra::Texture::TextureType::Texture1DBuffer:
|
||||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D);
|
result.texture_type.Assign(Tegra::Shader::TextureType::Texture1D);
|
||||||
result.is_array.Assign(0);
|
result.is_array.Assign(0);
|
||||||
result.is_buffer.Assign(1);
|
result.is_buffer.Assign(1);
|
||||||
result.is_shadow.Assign(0);
|
result.is_shadow.Assign(0);
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
case Tegra::Texture::TextureType::Texture2DNoMipmap:
|
case Tegra::Texture::TextureType::Texture2DNoMipmap:
|
||||||
result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D);
|
result.texture_type.Assign(Tegra::Shader::TextureType::Texture2D);
|
||||||
result.is_array.Assign(0);
|
result.is_array.Assign(0);
|
||||||
|
@ -105,7 +108,7 @@ static_assert(std::is_trivially_copyable_v<SamplerDescriptor>);
|
||||||
|
|
||||||
class ConstBufferEngineInterface {
|
class ConstBufferEngineInterface {
|
||||||
public:
|
public:
|
||||||
virtual ~ConstBufferEngineInterface() {}
|
virtual ~ConstBufferEngineInterface() = default;
|
||||||
virtual u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const = 0;
|
virtual u32 AccessConstBuffer32(ShaderType stage, u64 const_buffer, u64 offset) const = 0;
|
||||||
virtual SamplerDescriptor AccessBoundSampler(ShaderType stage, u64 offset) const = 0;
|
virtual SamplerDescriptor AccessBoundSampler(ShaderType stage, u64 offset) const = 0;
|
||||||
virtual SamplerDescriptor AccessBindlessSampler(ShaderType stage, u64 const_buffer,
|
virtual SamplerDescriptor AccessBindlessSampler(ShaderType stage, u64 const_buffer,
|
||||||
|
|
|
@ -22,6 +22,8 @@ ConstBufferLocker::ConstBufferLocker(Tegra::Engines::ShaderType shader_stage,
|
||||||
Tegra::Engines::ConstBufferEngineInterface& engine)
|
Tegra::Engines::ConstBufferEngineInterface& engine)
|
||||||
: stage{shader_stage}, engine{&engine} {}
|
: stage{shader_stage}, engine{&engine} {}
|
||||||
|
|
||||||
|
ConstBufferLocker::~ConstBufferLocker() = default;
|
||||||
|
|
||||||
std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) {
|
std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) {
|
||||||
const std::pair<u32, u32> key = {buffer, offset};
|
const std::pair<u32, u32> key = {buffer, offset};
|
||||||
const auto iter = keys.find(key);
|
const auto iter = keys.find(key);
|
||||||
|
@ -29,7 +31,7 @@ std::optional<u32> ConstBufferLocker::ObtainKey(u32 buffer, u32 offset) {
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
const u32 value = engine->AccessConstBuffer32(stage, buffer, offset);
|
const u32 value = engine->AccessConstBuffer32(stage, buffer, offset);
|
||||||
keys.emplace(key, value);
|
keys.emplace(key, value);
|
||||||
|
@ -43,7 +45,7 @@ std::optional<SamplerDescriptor> ConstBufferLocker::ObtainBoundSampler(u32 offse
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
const SamplerDescriptor value = engine->AccessBoundSampler(stage, offset);
|
const SamplerDescriptor value = engine->AccessBoundSampler(stage, offset);
|
||||||
bound_samplers.emplace(key, value);
|
bound_samplers.emplace(key, value);
|
||||||
|
@ -58,7 +60,7 @@ std::optional<Tegra::Engines::SamplerDescriptor> ConstBufferLocker::ObtainBindle
|
||||||
return iter->second;
|
return iter->second;
|
||||||
}
|
}
|
||||||
if (!engine) {
|
if (!engine) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
const SamplerDescriptor value = engine->AccessBindlessSampler(stage, buffer, offset);
|
const SamplerDescriptor value = engine->AccessBindlessSampler(stage, buffer, offset);
|
||||||
bindless_samplers.emplace(key, value);
|
bindless_samplers.emplace(key, value);
|
||||||
|
|
|
@ -16,6 +16,11 @@ using BoundSamplerMap = std::unordered_map<u32, Tegra::Engines::SamplerDescripto
|
||||||
using BindlessSamplerMap =
|
using BindlessSamplerMap =
|
||||||
std::unordered_map<std::pair<u32, u32>, Tegra::Engines::SamplerDescriptor, Common::PairHash>;
|
std::unordered_map<std::pair<u32, u32>, Tegra::Engines::SamplerDescriptor, Common::PairHash>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ConstBufferLocker is a class use to interface the 3D and compute engines with the shader
|
||||||
|
* compiler. with it, the shader can obtain required data from GPU state and store it for disk
|
||||||
|
* shader compilation.
|
||||||
|
**/
|
||||||
class ConstBufferLocker {
|
class ConstBufferLocker {
|
||||||
public:
|
public:
|
||||||
explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage);
|
explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage);
|
||||||
|
@ -23,6 +28,8 @@ public:
|
||||||
explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage,
|
explicit ConstBufferLocker(Tegra::Engines::ShaderType shader_stage,
|
||||||
Tegra::Engines::ConstBufferEngineInterface& engine);
|
Tegra::Engines::ConstBufferEngineInterface& engine);
|
||||||
|
|
||||||
|
~ConstBufferLocker();
|
||||||
|
|
||||||
/// Retrieves a key from the locker, if it's registered, it will give the registered value, if
|
/// Retrieves a key from the locker, if it's registered, it will give the registered value, if
|
||||||
/// not it will obtain it from maxwell3d and register it.
|
/// not it will obtain it from maxwell3d and register it.
|
||||||
std::optional<u32> ObtainKey(u32 buffer, u32 offset);
|
std::optional<u32> ObtainKey(u32 buffer, u32 offset);
|
||||||
|
|
|
@ -41,14 +41,10 @@ BlockBranchInfo MakeBranchInfo(Args&&... args) {
|
||||||
return std::make_shared<BranchData>(T(std::forward<Args>(args)...));
|
return std::make_shared<BranchData>(T(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BlockBranchInfoAreEqual(BlockBranchInfo first, BlockBranchInfo second) {
|
|
||||||
return false; //(*first) == (*second);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockBranchIsIgnored(BlockBranchInfo first) {
|
bool BlockBranchIsIgnored(BlockBranchInfo first) {
|
||||||
bool ignore = false;
|
bool ignore = false;
|
||||||
if (std::holds_alternative<SingleBranch>(*first)) {
|
if (std::holds_alternative<SingleBranch>(*first)) {
|
||||||
auto branch = std::get_if<SingleBranch>(first.get());
|
const auto branch = std::get_if<SingleBranch>(first.get());
|
||||||
ignore = branch->ignore;
|
ignore = branch->ignore;
|
||||||
}
|
}
|
||||||
return ignore;
|
return ignore;
|
||||||
|
@ -151,10 +147,10 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
|
||||||
const Instruction instr = {state.program_code[pos]};
|
const Instruction instr = {state.program_code[pos]};
|
||||||
const auto opcode = OpCode::Decode(instr);
|
const auto opcode = OpCode::Decode(instr);
|
||||||
if (opcode->get().GetId() != OpCode::Id::BRX) {
|
if (opcode->get().GetId() != OpCode::Id::BRX) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
if (instr.brx.constant_buffer != 0) {
|
if (instr.brx.constant_buffer != 0) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
track_register = instr.gpr8.Value();
|
track_register = instr.gpr8.Value();
|
||||||
result.relative_position = instr.brx.GetBranchExtend();
|
result.relative_position = instr.brx.GetBranchExtend();
|
||||||
|
@ -172,8 +168,8 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
|
||||||
if (opcode->get().GetId() == OpCode::Id::LD_C) {
|
if (opcode->get().GetId() == OpCode::Id::LD_C) {
|
||||||
if (instr.gpr0.Value() == track_register &&
|
if (instr.gpr0.Value() == track_register &&
|
||||||
instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) {
|
instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) {
|
||||||
result.buffer = instr.cbuf36.index;
|
result.buffer = instr.cbuf36.index.Value();
|
||||||
result.offset = instr.cbuf36.GetOffset();
|
result.offset = static_cast<u32>(instr.cbuf36.GetOffset());
|
||||||
track_register = instr.gpr8.Value();
|
track_register = instr.gpr8.Value();
|
||||||
pos--;
|
pos--;
|
||||||
found_track = true;
|
found_track = true;
|
||||||
|
@ -184,7 +180,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_track) {
|
if (!found_track) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
found_track = false;
|
found_track = false;
|
||||||
|
|
||||||
|
@ -194,7 +190,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
|
||||||
pos--;
|
pos--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const Instruction instr = {state.program_code[pos]};
|
const Instruction instr = state.program_code[pos];
|
||||||
const auto opcode = OpCode::Decode(instr);
|
const auto opcode = OpCode::Decode(instr);
|
||||||
if (opcode->get().GetId() == OpCode::Id::SHL_IMM) {
|
if (opcode->get().GetId() == OpCode::Id::SHL_IMM) {
|
||||||
if (instr.gpr0.Value() == track_register) {
|
if (instr.gpr0.Value() == track_register) {
|
||||||
|
@ -208,7 +204,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_track) {
|
if (!found_track) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
found_track = false;
|
found_track = false;
|
||||||
|
|
||||||
|
@ -218,7 +214,7 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
|
||||||
pos--;
|
pos--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const Instruction instr = {state.program_code[pos]};
|
const Instruction instr = state.program_code[pos];
|
||||||
const auto opcode = OpCode::Decode(instr);
|
const auto opcode = OpCode::Decode(instr);
|
||||||
if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) {
|
if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) {
|
||||||
if (instr.gpr0.Value() == track_register) {
|
if (instr.gpr0.Value() == track_register) {
|
||||||
|
@ -233,9 +229,9 @@ std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState&
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_track) {
|
if (!found_track) {
|
||||||
return {};
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
return {result};
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) {
|
std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) {
|
||||||
|
@ -440,8 +436,8 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
|
||||||
branches.emplace_back(value, target);
|
branches.emplace_back(value, target);
|
||||||
}
|
}
|
||||||
parse_info.end_address = offset;
|
parse_info.end_address = offset;
|
||||||
parse_info.branch_info =
|
parse_info.branch_info = MakeBranchInfo<MultiBranch>(
|
||||||
MakeBranchInfo<MultiBranch>(static_cast<u32>(instr.gpr8.Value()), branches);
|
static_cast<u32>(instr.gpr8.Value()), std::move(branches));
|
||||||
|
|
||||||
return {ParseResult::ControlCaught, parse_info};
|
return {ParseResult::ControlCaught, parse_info};
|
||||||
} else {
|
} else {
|
||||||
|
@ -486,7 +482,7 @@ bool TryInspectAddress(CFGRebuildState& state) {
|
||||||
current_block.end = address - 1;
|
current_block.end = address - 1;
|
||||||
new_block.branch = current_block.branch;
|
new_block.branch = current_block.branch;
|
||||||
BlockBranchInfo forward_branch = MakeBranchInfo<SingleBranch>();
|
BlockBranchInfo forward_branch = MakeBranchInfo<SingleBranch>();
|
||||||
auto branch = std::get_if<SingleBranch>(forward_branch.get());
|
const auto branch = std::get_if<SingleBranch>(forward_branch.get());
|
||||||
branch->address = address;
|
branch->address = address;
|
||||||
branch->ignore = true;
|
branch->ignore = true;
|
||||||
current_block.branch = forward_branch;
|
current_block.branch = forward_branch;
|
||||||
|
@ -504,7 +500,7 @@ bool TryInspectAddress(CFGRebuildState& state) {
|
||||||
BlockInfo& block_info = CreateBlockInfo(state, address, parse_info.end_address);
|
BlockInfo& block_info = CreateBlockInfo(state, address, parse_info.end_address);
|
||||||
block_info.branch = parse_info.branch_info;
|
block_info.branch = parse_info.branch_info;
|
||||||
if (std::holds_alternative<SingleBranch>(*block_info.branch)) {
|
if (std::holds_alternative<SingleBranch>(*block_info.branch)) {
|
||||||
auto branch = std::get_if<SingleBranch>(block_info.branch.get());
|
const auto branch = std::get_if<SingleBranch>(block_info.branch.get());
|
||||||
if (branch->condition.IsUnconditional()) {
|
if (branch->condition.IsUnconditional()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -550,7 +546,7 @@ bool TryQuery(CFGRebuildState& state) {
|
||||||
gather_labels(q2.ssy_stack, state.ssy_labels, block);
|
gather_labels(q2.ssy_stack, state.ssy_labels, block);
|
||||||
gather_labels(q2.pbk_stack, state.pbk_labels, block);
|
gather_labels(q2.pbk_stack, state.pbk_labels, block);
|
||||||
if (std::holds_alternative<SingleBranch>(*block.branch)) {
|
if (std::holds_alternative<SingleBranch>(*block.branch)) {
|
||||||
auto branch = std::get_if<SingleBranch>(block.branch.get());
|
const auto branch = std::get_if<SingleBranch>(block.branch.get());
|
||||||
if (!branch->condition.IsUnconditional()) {
|
if (!branch->condition.IsUnconditional()) {
|
||||||
q2.address = block.end + 1;
|
q2.address = block.end + 1;
|
||||||
state.queries.push_back(q2);
|
state.queries.push_back(q2);
|
||||||
|
@ -573,8 +569,8 @@ bool TryQuery(CFGRebuildState& state) {
|
||||||
state.queries.push_back(std::move(conditional_query));
|
state.queries.push_back(std::move(conditional_query));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto multi_branch = std::get_if<MultiBranch>(block.branch.get());
|
const auto multi_branch = std::get_if<MultiBranch>(block.branch.get());
|
||||||
for (auto& branch_case : multi_branch->branches) {
|
for (const auto& branch_case : multi_branch->branches) {
|
||||||
Query conditional_query{q2};
|
Query conditional_query{q2};
|
||||||
conditional_query.address = branch_case.address;
|
conditional_query.address = branch_case.address;
|
||||||
state.queries.push_back(std::move(conditional_query));
|
state.queries.push_back(std::move(conditional_query));
|
||||||
|
@ -612,7 +608,7 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) {
|
||||||
return MakeExpr<ExprBoolean>(true);
|
return MakeExpr<ExprBoolean>(true);
|
||||||
});
|
});
|
||||||
if (std::holds_alternative<SingleBranch>(*branch_info)) {
|
if (std::holds_alternative<SingleBranch>(*branch_info)) {
|
||||||
auto branch = std::get_if<SingleBranch>(branch_info.get());
|
const auto branch = std::get_if<SingleBranch>(branch_info.get());
|
||||||
if (branch->address < 0) {
|
if (branch->address < 0) {
|
||||||
if (branch->kill) {
|
if (branch->kill) {
|
||||||
mm.InsertReturn(get_expr(branch->condition), true);
|
mm.InsertReturn(get_expr(branch->condition), true);
|
||||||
|
@ -624,8 +620,8 @@ void InsertBranch(ASTManager& mm, const BlockBranchInfo& branch_info) {
|
||||||
mm.InsertGoto(get_expr(branch->condition), branch->address);
|
mm.InsertGoto(get_expr(branch->condition), branch->address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto multi_branch = std::get_if<MultiBranch>(branch_info.get());
|
const auto multi_branch = std::get_if<MultiBranch>(branch_info.get());
|
||||||
for (auto& branch_case : multi_branch->branches) {
|
for (const auto& branch_case : multi_branch->branches) {
|
||||||
mm.InsertGoto(MakeExpr<ExprGprEqual>(multi_branch->gpr, branch_case.cmp_value),
|
mm.InsertGoto(MakeExpr<ExprGprEqual>(multi_branch->gpr, branch_case.cmp_value),
|
||||||
branch_case.address);
|
branch_case.address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,10 @@ public:
|
||||||
std::tie(b.condition, b.address, b.kill, b.is_sync, b.is_brk, b.ignore);
|
std::tie(b.condition, b.address, b.kill, b.is_sync, b.is_brk, b.ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!=(const SingleBranch& b) const {
|
||||||
|
return !operator==(b);
|
||||||
|
}
|
||||||
|
|
||||||
Condition condition{};
|
Condition condition{};
|
||||||
s32 address{exit_branch};
|
s32 address{exit_branch};
|
||||||
bool kill{};
|
bool kill{};
|
||||||
|
@ -67,7 +71,7 @@ struct CaseBranch {
|
||||||
|
|
||||||
class MultiBranch {
|
class MultiBranch {
|
||||||
public:
|
public:
|
||||||
MultiBranch(u32 gpr, std::vector<CaseBranch>& branches)
|
MultiBranch(u32 gpr, std::vector<CaseBranch>&& branches)
|
||||||
: gpr{gpr}, branches{std::move(branches)} {}
|
: gpr{gpr}, branches{std::move(branches)} {}
|
||||||
|
|
||||||
u32 gpr{};
|
u32 gpr{};
|
||||||
|
|
|
@ -155,7 +155,7 @@ void ShaderIR::Decode() {
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case CompileDepth::BruteForce: {
|
case CompileDepth::BruteForce: {
|
||||||
coverage_begin = main_offset;
|
coverage_begin = main_offset;
|
||||||
const u32 shader_end = program_code.size();
|
const std::size_t shader_end = program_code.size();
|
||||||
coverage_end = shader_end;
|
coverage_end = shader_end;
|
||||||
for (u32 label = main_offset; label < shader_end; label++) {
|
for (u32 label = main_offset; label < shader_end; label++) {
|
||||||
basic_blocks.insert({label, DecodeRange(label, label + 1)});
|
basic_blocks.insert({label, DecodeRange(label, label + 1)});
|
||||||
|
|
|
@ -284,7 +284,7 @@ u32 ShaderIR::DecodeTexture(NodeBlock& bb, u32 pc) {
|
||||||
|
|
||||||
const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
|
const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
|
||||||
std::optional<SamplerInfo> sampler_info) {
|
std::optional<SamplerInfo> sampler_info) {
|
||||||
const auto offset = static_cast<std::size_t>(sampler.index.Value());
|
const auto offset = static_cast<u32>(sampler.index.Value());
|
||||||
|
|
||||||
Tegra::Shader::TextureType type;
|
Tegra::Shader::TextureType type;
|
||||||
bool is_array;
|
bool is_array;
|
||||||
|
@ -293,9 +293,7 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
|
||||||
type = sampler_info->type;
|
type = sampler_info->type;
|
||||||
is_array = sampler_info->is_array;
|
is_array = sampler_info->is_array;
|
||||||
is_shadow = sampler_info->is_shadow;
|
is_shadow = sampler_info->is_shadow;
|
||||||
} else {
|
} else if (auto sampler = locker.ObtainBoundSampler(offset); sampler) {
|
||||||
auto sampler = locker.ObtainBoundSampler(offset);
|
|
||||||
if (sampler) {
|
|
||||||
type = sampler->texture_type.Value();
|
type = sampler->texture_type.Value();
|
||||||
is_array = sampler->is_array.Value() != 0;
|
is_array = sampler->is_array.Value() != 0;
|
||||||
is_shadow = sampler->is_shadow.Value() != 0;
|
is_shadow = sampler->is_shadow.Value() != 0;
|
||||||
|
@ -304,7 +302,6 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
|
||||||
is_array = false;
|
is_array = false;
|
||||||
is_shadow = false;
|
is_shadow = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If this sampler has already been used, return the existing mapping.
|
// If this sampler has already been used, return the existing mapping.
|
||||||
const auto itr =
|
const auto itr =
|
||||||
|
@ -320,7 +317,7 @@ const Sampler& ShaderIR::GetSampler(const Tegra::Shader::Sampler& sampler,
|
||||||
const std::size_t next_index = used_samplers.size();
|
const std::size_t next_index = used_samplers.size();
|
||||||
const Sampler entry{offset, next_index, type, is_array, is_shadow};
|
const Sampler entry{offset, next_index, type, is_array, is_shadow};
|
||||||
return *used_samplers.emplace(entry).first;
|
return *used_samplers.emplace(entry).first;
|
||||||
}
|
} // namespace VideoCommon::Shader
|
||||||
|
|
||||||
const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
|
const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
|
||||||
std::optional<SamplerInfo> sampler_info) {
|
std::optional<SamplerInfo> sampler_info) {
|
||||||
|
@ -336,9 +333,7 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
|
||||||
type = sampler_info->type;
|
type = sampler_info->type;
|
||||||
is_array = sampler_info->is_array;
|
is_array = sampler_info->is_array;
|
||||||
is_shadow = sampler_info->is_shadow;
|
is_shadow = sampler_info->is_shadow;
|
||||||
} else {
|
} else if (auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset); sampler) {
|
||||||
auto sampler = locker.ObtainBindlessSampler(cbuf_index, cbuf_offset);
|
|
||||||
if (sampler) {
|
|
||||||
type = sampler->texture_type.Value();
|
type = sampler->texture_type.Value();
|
||||||
is_array = sampler->is_array.Value() != 0;
|
is_array = sampler->is_array.Value() != 0;
|
||||||
is_shadow = sampler->is_shadow.Value() != 0;
|
is_shadow = sampler->is_shadow.Value() != 0;
|
||||||
|
@ -347,7 +342,6 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
|
||||||
is_array = false;
|
is_array = false;
|
||||||
is_shadow = false;
|
is_shadow = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If this sampler has already been used, return the existing mapping.
|
// If this sampler has already been used, return the existing mapping.
|
||||||
const auto itr =
|
const auto itr =
|
||||||
|
|
|
@ -127,6 +127,10 @@ public:
|
||||||
return gpr == b.gpr && value == b.value;
|
return gpr == b.gpr && value == b.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!=(const ExprGprEqual& b) const {
|
||||||
|
return !operator==(b);
|
||||||
|
}
|
||||||
|
|
||||||
u32 gpr;
|
u32 gpr;
|
||||||
u32 value;
|
u32 value;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue