shader_recompiler,video_core: Cleanup some GCC and Clang errors
Mostly fixing unused *, implicit conversion, braced scalar init, fpermissive, and some others. Some Clang errors likely remain in video_core, and std::ranges is still a pertinent issue in shader_recompiler shader_recompiler: cmake: Force bracket depth to 1024 on Clang Increases the maximum fold expression depth thread_worker: Include condition_variable Don't use list initializers in control flow Co-authored-by: ReinUsesLisp <reinuseslisp@airmail.cc>
This commit is contained in:
		@@ -6,6 +6,7 @@
 | 
			
		||||
#include "shader_recompiler/frontend/ir/microinstruction.h"
 | 
			
		||||
#include "shader_recompiler/frontend/ir/modifiers.h"
 | 
			
		||||
#include "shader_recompiler/frontend/ir/program.h"
 | 
			
		||||
#include "shader_recompiler/ir_opt/passes.h"
 | 
			
		||||
#include "shader_recompiler/shader_info.h"
 | 
			
		||||
 | 
			
		||||
namespace Shader::Optimization {
 | 
			
		||||
@@ -22,8 +23,8 @@ void AddConstantBufferDescriptor(Info& info, u32 index, u32 count) {
 | 
			
		||||
    auto& cbufs{info.constant_buffer_descriptors};
 | 
			
		||||
    cbufs.insert(std::ranges::lower_bound(cbufs, index, {}, &ConstantBufferDescriptor::index),
 | 
			
		||||
                 ConstantBufferDescriptor{
 | 
			
		||||
                     .index{index},
 | 
			
		||||
                     .count{1},
 | 
			
		||||
                     .index = index,
 | 
			
		||||
                     .count = 1,
 | 
			
		||||
                 });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -91,7 +92,7 @@ void SetAttribute(Info& info, IR::Attribute attribute) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::CompositeConstructF16x2:
 | 
			
		||||
    case IR::Opcode::CompositeConstructF16x3:
 | 
			
		||||
    case IR::Opcode::CompositeConstructF16x4:
 | 
			
		||||
@@ -209,7 +210,7 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::GetCbufU8:
 | 
			
		||||
    case IR::Opcode::GetCbufS8:
 | 
			
		||||
    case IR::Opcode::UndefU8:
 | 
			
		||||
@@ -236,7 +237,7 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::GetCbufU16:
 | 
			
		||||
    case IR::Opcode::GetCbufS16:
 | 
			
		||||
    case IR::Opcode::UndefU16:
 | 
			
		||||
@@ -271,7 +272,7 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::UndefU64:
 | 
			
		||||
    case IR::Opcode::LoadGlobalU8:
 | 
			
		||||
    case IR::Opcode::LoadGlobalS8:
 | 
			
		||||
@@ -314,7 +315,7 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::DemoteToHelperInvocation:
 | 
			
		||||
        info.uses_demote_to_helper_invocation = true;
 | 
			
		||||
        break;
 | 
			
		||||
@@ -361,7 +362,7 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
        } else {
 | 
			
		||||
            throw NotImplementedException("Constant buffer with non-immediate index");
 | 
			
		||||
        }
 | 
			
		||||
        switch (inst.Opcode()) {
 | 
			
		||||
        switch (inst.GetOpcode()) {
 | 
			
		||||
        case IR::Opcode::GetCbufU8:
 | 
			
		||||
        case IR::Opcode::GetCbufS8:
 | 
			
		||||
            info.used_constant_buffer_types |= IR::Type::U8;
 | 
			
		||||
@@ -443,7 +444,7 @@ void VisitUsages(Info& info, IR::Inst& inst) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VisitFpModifiers(Info& info, IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::FPAdd16:
 | 
			
		||||
    case IR::Opcode::FPFma16:
 | 
			
		||||
    case IR::Opcode::FPMul16:
 | 
			
		||||
@@ -540,7 +541,6 @@ void GatherInfoFromHeader(Environment& env, Info& info) {
 | 
			
		||||
        info.stores_position |= header.vtg.omap_systemb.position != 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
 | 
			
		||||
void CollectShaderInfoPass(Environment& env, IR::Program& program) {
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ bool FoldCommutative(IR::Inst& inst, ImmFn&& imm_fn) {
 | 
			
		||||
    }
 | 
			
		||||
    if (is_lhs_immediate && !is_rhs_immediate) {
 | 
			
		||||
        IR::Inst* const rhs_inst{rhs.InstRecursive()};
 | 
			
		||||
        if (rhs_inst->Opcode() == inst.Opcode() && rhs_inst->Arg(1).IsImmediate()) {
 | 
			
		||||
        if (rhs_inst->GetOpcode() == inst.GetOpcode() && rhs_inst->Arg(1).IsImmediate()) {
 | 
			
		||||
            const auto combined{imm_fn(Arg<T>(lhs), Arg<T>(rhs_inst->Arg(1)))};
 | 
			
		||||
            inst.SetArg(0, rhs_inst->Arg(0));
 | 
			
		||||
            inst.SetArg(1, IR::Value{combined});
 | 
			
		||||
@@ -70,7 +70,7 @@ bool FoldCommutative(IR::Inst& inst, ImmFn&& imm_fn) {
 | 
			
		||||
    }
 | 
			
		||||
    if (!is_lhs_immediate && is_rhs_immediate) {
 | 
			
		||||
        const IR::Inst* const lhs_inst{lhs.InstRecursive()};
 | 
			
		||||
        if (lhs_inst->Opcode() == inst.Opcode() && lhs_inst->Arg(1).IsImmediate()) {
 | 
			
		||||
        if (lhs_inst->GetOpcode() == inst.GetOpcode() && lhs_inst->Arg(1).IsImmediate()) {
 | 
			
		||||
            const auto combined{imm_fn(Arg<T>(rhs), Arg<T>(lhs_inst->Arg(1)))};
 | 
			
		||||
            inst.SetArg(0, lhs_inst->Arg(0));
 | 
			
		||||
            inst.SetArg(1, IR::Value{combined});
 | 
			
		||||
@@ -123,7 +123,8 @@ bool FoldXmadMultiply(IR::Block& block, IR::Inst& inst) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const lhs_shl{lhs_arg.InstRecursive()};
 | 
			
		||||
    if (lhs_shl->Opcode() != IR::Opcode::ShiftLeftLogical32 || lhs_shl->Arg(1) != IR::Value{16U}) {
 | 
			
		||||
    if (lhs_shl->GetOpcode() != IR::Opcode::ShiftLeftLogical32 ||
 | 
			
		||||
        lhs_shl->Arg(1) != IR::Value{16U}) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (lhs_shl->Arg(0).IsImmediate()) {
 | 
			
		||||
@@ -131,7 +132,7 @@ bool FoldXmadMultiply(IR::Block& block, IR::Inst& inst) {
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const lhs_mul{lhs_shl->Arg(0).InstRecursive()};
 | 
			
		||||
    IR::Inst* const rhs_mul{rhs_arg.InstRecursive()};
 | 
			
		||||
    if (lhs_mul->Opcode() != IR::Opcode::IMul32 || rhs_mul->Opcode() != IR::Opcode::IMul32) {
 | 
			
		||||
    if (lhs_mul->GetOpcode() != IR::Opcode::IMul32 || rhs_mul->GetOpcode() != IR::Opcode::IMul32) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (lhs_mul->Arg(1).Resolve() != rhs_mul->Arg(1).Resolve()) {
 | 
			
		||||
@@ -143,10 +144,10 @@ bool FoldXmadMultiply(IR::Block& block, IR::Inst& inst) {
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const lhs_bfe{lhs_mul->Arg(0).InstRecursive()};
 | 
			
		||||
    IR::Inst* const rhs_bfe{rhs_mul->Arg(0).InstRecursive()};
 | 
			
		||||
    if (lhs_bfe->Opcode() != IR::Opcode::BitFieldUExtract) {
 | 
			
		||||
    if (lhs_bfe->GetOpcode() != IR::Opcode::BitFieldUExtract) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (rhs_bfe->Opcode() != IR::Opcode::BitFieldUExtract) {
 | 
			
		||||
    if (rhs_bfe->GetOpcode() != IR::Opcode::BitFieldUExtract) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    if (lhs_bfe->Arg(1) != IR::Value{16U} || lhs_bfe->Arg(2) != IR::Value{16U}) {
 | 
			
		||||
@@ -194,8 +195,9 @@ void FoldISub32(IR::Inst& inst) {
 | 
			
		||||
    // ISub32 is generally used to subtract two constant buffers, compare and replace this with
 | 
			
		||||
    // zero if they equal.
 | 
			
		||||
    const auto equal_cbuf{[](IR::Inst* a, IR::Inst* b) {
 | 
			
		||||
        return a->Opcode() == IR::Opcode::GetCbufU32 && b->Opcode() == IR::Opcode::GetCbufU32 &&
 | 
			
		||||
               a->Arg(0) == b->Arg(0) && a->Arg(1) == b->Arg(1);
 | 
			
		||||
        return a->GetOpcode() == IR::Opcode::GetCbufU32 &&
 | 
			
		||||
               b->GetOpcode() == IR::Opcode::GetCbufU32 && a->Arg(0) == b->Arg(0) &&
 | 
			
		||||
               a->Arg(1) == b->Arg(1);
 | 
			
		||||
    }};
 | 
			
		||||
    IR::Inst* op_a{inst.Arg(0).InstRecursive()};
 | 
			
		||||
    IR::Inst* op_b{inst.Arg(1).InstRecursive()};
 | 
			
		||||
@@ -204,15 +206,15 @@ void FoldISub32(IR::Inst& inst) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    // It's also possible a value is being added to a cbuf and then subtracted
 | 
			
		||||
    if (op_b->Opcode() == IR::Opcode::IAdd32) {
 | 
			
		||||
    if (op_b->GetOpcode() == IR::Opcode::IAdd32) {
 | 
			
		||||
        // Canonicalize local variables to simplify the following logic
 | 
			
		||||
        std::swap(op_a, op_b);
 | 
			
		||||
    }
 | 
			
		||||
    if (op_b->Opcode() != IR::Opcode::GetCbufU32) {
 | 
			
		||||
    if (op_b->GetOpcode() != IR::Opcode::GetCbufU32) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const inst_cbuf{op_b};
 | 
			
		||||
    if (op_a->Opcode() != IR::Opcode::IAdd32) {
 | 
			
		||||
    if (op_a->GetOpcode() != IR::Opcode::IAdd32) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    IR::Value add_op_a{op_a->Arg(0)};
 | 
			
		||||
@@ -250,7 +252,8 @@ void FoldFPMul32(IR::Inst& inst) {
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const lhs_op{lhs_value.InstRecursive()};
 | 
			
		||||
    IR::Inst* const rhs_op{rhs_value.InstRecursive()};
 | 
			
		||||
    if (lhs_op->Opcode() != IR::Opcode::FPMul32 || rhs_op->Opcode() != IR::Opcode::FPRecip32) {
 | 
			
		||||
    if (lhs_op->GetOpcode() != IR::Opcode::FPMul32 ||
 | 
			
		||||
        rhs_op->GetOpcode() != IR::Opcode::FPRecip32) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    const IR::Value recip_source{rhs_op->Arg(0)};
 | 
			
		||||
@@ -260,8 +263,8 @@ void FoldFPMul32(IR::Inst& inst) {
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const attr_a{recip_source.InstRecursive()};
 | 
			
		||||
    IR::Inst* const attr_b{lhs_mul_source.InstRecursive()};
 | 
			
		||||
    if (attr_a->Opcode() != IR::Opcode::GetAttribute ||
 | 
			
		||||
        attr_b->Opcode() != IR::Opcode::GetAttribute) {
 | 
			
		||||
    if (attr_a->GetOpcode() != IR::Opcode::GetAttribute ||
 | 
			
		||||
        attr_b->GetOpcode() != IR::Opcode::GetAttribute) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (attr_a->Arg(0).Attribute() == attr_b->Arg(0).Attribute()) {
 | 
			
		||||
@@ -304,7 +307,7 @@ void FoldLogicalNot(IR::Inst& inst) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const arg{value.InstRecursive()};
 | 
			
		||||
    if (arg->Opcode() == IR::Opcode::LogicalNot) {
 | 
			
		||||
    if (arg->GetOpcode() == IR::Opcode::LogicalNot) {
 | 
			
		||||
        inst.ReplaceUsesWith(arg->Arg(0));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -317,12 +320,12 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const arg_inst{value.InstRecursive()};
 | 
			
		||||
    if (arg_inst->Opcode() == reverse) {
 | 
			
		||||
    if (arg_inst->GetOpcode() == reverse) {
 | 
			
		||||
        inst.ReplaceUsesWith(arg_inst->Arg(0));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if constexpr (op == IR::Opcode::BitCastF32U32) {
 | 
			
		||||
        if (arg_inst->Opcode() == IR::Opcode::GetCbufU32) {
 | 
			
		||||
        if (arg_inst->GetOpcode() == IR::Opcode::GetCbufU32) {
 | 
			
		||||
            // Replace the bitcast with a typed constant buffer read
 | 
			
		||||
            inst.ReplaceOpcode(IR::Opcode::GetCbufF32);
 | 
			
		||||
            inst.SetArg(0, arg_inst->Arg(0));
 | 
			
		||||
@@ -338,7 +341,7 @@ void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    IR::Inst* const arg_inst{value.InstRecursive()};
 | 
			
		||||
    if (arg_inst->Opcode() == reverse) {
 | 
			
		||||
    if (arg_inst->GetOpcode() == reverse) {
 | 
			
		||||
        inst.ReplaceUsesWith(arg_inst->Arg(0));
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -347,7 +350,7 @@ void FoldInverseFunc(IR::Inst& inst, IR::Opcode reverse) {
 | 
			
		||||
template <typename Func, size_t... I>
 | 
			
		||||
IR::Value EvalImmediates(const IR::Inst& inst, Func&& func, std::index_sequence<I...>) {
 | 
			
		||||
    using Traits = LambdaTraits<decltype(func)>;
 | 
			
		||||
    return IR::Value{func(Arg<Traits::ArgType<I>>(inst.Arg(I))...)};
 | 
			
		||||
    return IR::Value{func(Arg<typename Traits::template ArgType<I>>(inst.Arg(I))...)};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FoldBranchConditional(IR::Inst& inst) {
 | 
			
		||||
@@ -357,7 +360,7 @@ void FoldBranchConditional(IR::Inst& inst) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    const IR::Inst* cond_inst{cond.InstRecursive()};
 | 
			
		||||
    if (cond_inst->Opcode() == IR::Opcode::LogicalNot) {
 | 
			
		||||
    if (cond_inst->GetOpcode() == IR::Opcode::LogicalNot) {
 | 
			
		||||
        const IR::Value true_label{inst.Arg(1)};
 | 
			
		||||
        const IR::Value false_label{inst.Arg(2)};
 | 
			
		||||
        // Remove negation on the conditional (take the parameter out of LogicalNot) and swap
 | 
			
		||||
@@ -371,10 +374,10 @@ void FoldBranchConditional(IR::Inst& inst) {
 | 
			
		||||
std::optional<IR::Value> FoldCompositeExtractImpl(IR::Value inst_value, IR::Opcode insert,
 | 
			
		||||
                                                  IR::Opcode construct, u32 first_index) {
 | 
			
		||||
    IR::Inst* const inst{inst_value.InstRecursive()};
 | 
			
		||||
    if (inst->Opcode() == construct) {
 | 
			
		||||
    if (inst->GetOpcode() == construct) {
 | 
			
		||||
        return inst->Arg(first_index);
 | 
			
		||||
    }
 | 
			
		||||
    if (inst->Opcode() != insert) {
 | 
			
		||||
    if (inst->GetOpcode() != insert) {
 | 
			
		||||
        return std::nullopt;
 | 
			
		||||
    }
 | 
			
		||||
    IR::Value value_index{inst->Arg(2)};
 | 
			
		||||
@@ -410,7 +413,7 @@ void FoldCompositeExtract(IR::Inst& inst, IR::Opcode construct, IR::Opcode inser
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::GetRegister:
 | 
			
		||||
        return FoldGetRegister(inst);
 | 
			
		||||
    case IR::Opcode::GetPred:
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ struct StorageInfo {
 | 
			
		||||
 | 
			
		||||
/// Returns true when the instruction is a global memory instruction
 | 
			
		||||
bool IsGlobalMemory(const IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::LoadGlobalS8:
 | 
			
		||||
    case IR::Opcode::LoadGlobalU8:
 | 
			
		||||
    case IR::Opcode::LoadGlobalS16:
 | 
			
		||||
@@ -80,7 +80,7 @@ bool IsGlobalMemory(const IR::Inst& inst) {
 | 
			
		||||
 | 
			
		||||
/// Returns true when the instruction is a global memory instruction
 | 
			
		||||
bool IsGlobalMemoryWrite(const IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::WriteGlobalS8:
 | 
			
		||||
    case IR::Opcode::WriteGlobalU8:
 | 
			
		||||
    case IR::Opcode::WriteGlobalS16:
 | 
			
		||||
@@ -140,7 +140,7 @@ bool MeetsBias(const StorageBufferAddr& storage_buffer, const Bias& bias) noexce
 | 
			
		||||
void DiscardGlobalMemory(IR::Block& block, IR::Inst& inst) {
 | 
			
		||||
    IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
 | 
			
		||||
    const IR::Value zero{u32{0}};
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::LoadGlobalS8:
 | 
			
		||||
    case IR::Opcode::LoadGlobalU8:
 | 
			
		||||
    case IR::Opcode::LoadGlobalS16:
 | 
			
		||||
@@ -164,7 +164,7 @@ void DiscardGlobalMemory(IR::Block& block, IR::Inst& inst) {
 | 
			
		||||
        inst.Invalidate();
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        throw LogicError("Invalid opcode to discard its global memory operation {}", inst.Opcode());
 | 
			
		||||
        throw LogicError("Invalid opcode to discard its global memory operation {}", inst.GetOpcode());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -184,7 +184,7 @@ std::optional<LowAddrInfo> TrackLowAddress(IR::Inst* inst) {
 | 
			
		||||
    // This address is expected to either be a PackUint2x32 or a IAdd64
 | 
			
		||||
    IR::Inst* addr_inst{addr.InstRecursive()};
 | 
			
		||||
    s32 imm_offset{0};
 | 
			
		||||
    if (addr_inst->Opcode() == IR::Opcode::IAdd64) {
 | 
			
		||||
    if (addr_inst->GetOpcode() == IR::Opcode::IAdd64) {
 | 
			
		||||
        // If it's an IAdd64, get the immediate offset it is applying and grab the address
 | 
			
		||||
        // instruction. This expects for the instruction to be canonicalized having the address on
 | 
			
		||||
        // the first argument and the immediate offset on the second one.
 | 
			
		||||
@@ -200,7 +200,7 @@ std::optional<LowAddrInfo> TrackLowAddress(IR::Inst* inst) {
 | 
			
		||||
        addr_inst = iadd_addr.Inst();
 | 
			
		||||
    }
 | 
			
		||||
    // With IAdd64 handled, now PackUint2x32 is expected without exceptions
 | 
			
		||||
    if (addr_inst->Opcode() != IR::Opcode::PackUint2x32) {
 | 
			
		||||
    if (addr_inst->GetOpcode() != IR::Opcode::PackUint2x32) {
 | 
			
		||||
        return std::nullopt;
 | 
			
		||||
    }
 | 
			
		||||
    // PackUint2x32 is expected to be generated from a vector
 | 
			
		||||
@@ -210,20 +210,20 @@ std::optional<LowAddrInfo> TrackLowAddress(IR::Inst* inst) {
 | 
			
		||||
    }
 | 
			
		||||
    // This vector is expected to be a CompositeConstructU32x2
 | 
			
		||||
    IR::Inst* const vector_inst{vector.InstRecursive()};
 | 
			
		||||
    if (vector_inst->Opcode() != IR::Opcode::CompositeConstructU32x2) {
 | 
			
		||||
    if (vector_inst->GetOpcode() != IR::Opcode::CompositeConstructU32x2) {
 | 
			
		||||
        return std::nullopt;
 | 
			
		||||
    }
 | 
			
		||||
    // Grab the first argument from the CompositeConstructU32x2, this is the low address.
 | 
			
		||||
    return LowAddrInfo{
 | 
			
		||||
        .value{IR::U32{vector_inst->Arg(0)}},
 | 
			
		||||
        .imm_offset{imm_offset},
 | 
			
		||||
        .imm_offset = imm_offset,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Tries to track the storage buffer address used by a global memory instruction
 | 
			
		||||
std::optional<StorageBufferAddr> Track(const IR::Value& value, const Bias* bias) {
 | 
			
		||||
    const auto pred{[bias](const IR::Inst* inst) -> std::optional<StorageBufferAddr> {
 | 
			
		||||
        if (inst->Opcode() != IR::Opcode::GetCbufU32) {
 | 
			
		||||
        if (inst->GetOpcode() != IR::Opcode::GetCbufU32) {
 | 
			
		||||
            return std::nullopt;
 | 
			
		||||
        }
 | 
			
		||||
        const IR::Value index{inst->Arg(0)};
 | 
			
		||||
@@ -256,9 +256,9 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageInfo& info)
 | 
			
		||||
    // NVN puts storage buffers in a specific range, we have to bias towards these addresses to
 | 
			
		||||
    // avoid getting false positives
 | 
			
		||||
    static constexpr Bias nvn_bias{
 | 
			
		||||
        .index{0},
 | 
			
		||||
        .offset_begin{0x110},
 | 
			
		||||
        .offset_end{0x610},
 | 
			
		||||
        .index = 0,
 | 
			
		||||
        .offset_begin = 0x110,
 | 
			
		||||
        .offset_end = 0x610,
 | 
			
		||||
    };
 | 
			
		||||
    // Track the low address of the instruction
 | 
			
		||||
    const std::optional<LowAddrInfo> low_addr_info{TrackLowAddress(&inst)};
 | 
			
		||||
@@ -286,8 +286,8 @@ void CollectStorageBuffers(IR::Block& block, IR::Inst& inst, StorageInfo& info)
 | 
			
		||||
    info.set.insert(*storage_buffer);
 | 
			
		||||
    info.to_replace.push_back(StorageInst{
 | 
			
		||||
        .storage_buffer{*storage_buffer},
 | 
			
		||||
        .inst{&inst},
 | 
			
		||||
        .block{&block},
 | 
			
		||||
        .inst = &inst,
 | 
			
		||||
        .block = &block,
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -312,7 +312,7 @@ IR::U32 StorageOffset(IR::Block& block, IR::Inst& inst, StorageBufferAddr buffer
 | 
			
		||||
/// Replace a global memory load instruction with its storage buffer equivalent
 | 
			
		||||
void ReplaceLoad(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
 | 
			
		||||
                 const IR::U32& offset) {
 | 
			
		||||
    const IR::Opcode new_opcode{GlobalToStorage(inst.Opcode())};
 | 
			
		||||
    const IR::Opcode new_opcode{GlobalToStorage(inst.GetOpcode())};
 | 
			
		||||
    const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
 | 
			
		||||
    const IR::Value value{&*block.PrependNewInst(it, new_opcode, {storage_index, offset})};
 | 
			
		||||
    inst.ReplaceUsesWith(value);
 | 
			
		||||
@@ -321,7 +321,7 @@ void ReplaceLoad(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
 | 
			
		||||
/// Replace a global memory write instruction with its storage buffer equivalent
 | 
			
		||||
void ReplaceWrite(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
 | 
			
		||||
                  const IR::U32& offset) {
 | 
			
		||||
    const IR::Opcode new_opcode{GlobalToStorage(inst.Opcode())};
 | 
			
		||||
    const IR::Opcode new_opcode{GlobalToStorage(inst.GetOpcode())};
 | 
			
		||||
    const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
 | 
			
		||||
    block.PrependNewInst(it, new_opcode, {storage_index, offset, inst.Arg(1)});
 | 
			
		||||
    inst.Invalidate();
 | 
			
		||||
@@ -330,7 +330,7 @@ void ReplaceWrite(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index
 | 
			
		||||
/// Replace a global memory instruction with its storage buffer equivalent
 | 
			
		||||
void Replace(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
 | 
			
		||||
             const IR::U32& offset) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::LoadGlobalS8:
 | 
			
		||||
    case IR::Opcode::LoadGlobalU8:
 | 
			
		||||
    case IR::Opcode::LoadGlobalS16:
 | 
			
		||||
@@ -348,7 +348,7 @@ void Replace(IR::Block& block, IR::Inst& inst, const IR::U32& storage_index,
 | 
			
		||||
    case IR::Opcode::WriteGlobal128:
 | 
			
		||||
        return ReplaceWrite(block, inst, storage_index, offset);
 | 
			
		||||
    default:
 | 
			
		||||
        throw InvalidArgument("Invalid global memory opcode {}", inst.Opcode());
 | 
			
		||||
        throw InvalidArgument("Invalid global memory opcode {}", inst.GetOpcode());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
} // Anonymous namespace
 | 
			
		||||
@@ -366,9 +366,9 @@ void GlobalMemoryToStorageBufferPass(IR::Program& program) {
 | 
			
		||||
    u32 storage_index{};
 | 
			
		||||
    for (const StorageBufferAddr& storage_buffer : info.set) {
 | 
			
		||||
        program.info.storage_buffers_descriptors.push_back({
 | 
			
		||||
            .cbuf_index{storage_buffer.index},
 | 
			
		||||
            .cbuf_offset{storage_buffer.offset},
 | 
			
		||||
            .count{1},
 | 
			
		||||
            .cbuf_index = storage_buffer.index,
 | 
			
		||||
            .cbuf_offset = storage_buffer.offset,
 | 
			
		||||
            .count = 1,
 | 
			
		||||
            .is_written{info.writes.contains(storage_buffer)},
 | 
			
		||||
        });
 | 
			
		||||
        ++storage_index;
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,8 @@ void IdentityRemovalPass(IR::Program& program) {
 | 
			
		||||
                    inst->SetArg(i, arg.Inst()->Arg(0));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (inst->Opcode() == IR::Opcode::Identity || inst->Opcode() == IR::Opcode::Void) {
 | 
			
		||||
            if (inst->GetOpcode() == IR::Opcode::Identity ||
 | 
			
		||||
                inst->GetOpcode() == IR::Opcode::Void) {
 | 
			
		||||
                to_invalidate.push_back(&*inst);
 | 
			
		||||
                inst = block->Instructions().erase(inst);
 | 
			
		||||
            } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ IR::Opcode Replace(IR::Opcode op) {
 | 
			
		||||
void LowerFp16ToFp32(IR::Program& program) {
 | 
			
		||||
    for (IR::Block* const block : program.blocks) {
 | 
			
		||||
        for (IR::Inst& inst : block->Instructions()) {
 | 
			
		||||
            inst.ReplaceOpcode(Replace(inst.Opcode()));
 | 
			
		||||
            inst.ReplaceOpcode(Replace(inst.GetOpcode()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,7 @@ IR::Opcode UndefOpcode(IndirectBranchVariable) noexcept {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[[nodiscard]] bool IsPhi(const IR::Inst& inst) noexcept {
 | 
			
		||||
    return inst.Opcode() == IR::Opcode::Phi;
 | 
			
		||||
    return inst.GetOpcode() == IR::Opcode::Phi;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum class Status {
 | 
			
		||||
@@ -278,7 +278,7 @@ private:
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void VisitInst(Pass& pass, IR::Block* block, IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::SetRegister:
 | 
			
		||||
        if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) {
 | 
			
		||||
            pass.WriteVariable(reg, block, inst.Arg(1));
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,7 @@ struct TextureInst {
 | 
			
		||||
using TextureInstVector = boost::container::small_vector<TextureInst, 24>;
 | 
			
		||||
 | 
			
		||||
IR::Opcode IndexedInstruction(const IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::BindlessImageSampleImplicitLod:
 | 
			
		||||
    case IR::Opcode::BoundImageSampleImplicitLod:
 | 
			
		||||
        return IR::Opcode::ImageSampleImplicitLod;
 | 
			
		||||
@@ -67,7 +67,7 @@ IR::Opcode IndexedInstruction(const IR::Inst& inst) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool IsBindless(const IR::Inst& inst) {
 | 
			
		||||
    switch (inst.Opcode()) {
 | 
			
		||||
    switch (inst.GetOpcode()) {
 | 
			
		||||
    case IR::Opcode::BindlessImageSampleImplicitLod:
 | 
			
		||||
    case IR::Opcode::BindlessImageSampleExplicitLod:
 | 
			
		||||
    case IR::Opcode::BindlessImageSampleDrefImplicitLod:
 | 
			
		||||
@@ -91,7 +91,7 @@ bool IsBindless(const IR::Inst& inst) {
 | 
			
		||||
    case IR::Opcode::BoundImageGradient:
 | 
			
		||||
        return false;
 | 
			
		||||
    default:
 | 
			
		||||
        throw InvalidArgument("Invalid opcode {}", inst.Opcode());
 | 
			
		||||
        throw InvalidArgument("Invalid opcode {}", inst.GetOpcode());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -100,7 +100,7 @@ bool IsTextureInstruction(const IR::Inst& inst) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst) {
 | 
			
		||||
    if (inst->Opcode() != IR::Opcode::GetCbufU32) {
 | 
			
		||||
    if (inst->GetOpcode() != IR::Opcode::GetCbufU32) {
 | 
			
		||||
        return std::nullopt;
 | 
			
		||||
    }
 | 
			
		||||
    const IR::Value index{inst->Arg(0)};
 | 
			
		||||
@@ -134,14 +134,14 @@ TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
 | 
			
		||||
        addr = *track_addr;
 | 
			
		||||
    } else {
 | 
			
		||||
        addr = ConstBufferAddr{
 | 
			
		||||
            .index{env.TextureBoundBuffer()},
 | 
			
		||||
            .offset{inst.Arg(0).U32()},
 | 
			
		||||
            .index = env.TextureBoundBuffer(),
 | 
			
		||||
            .offset = inst.Arg(0).U32(),
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
    return TextureInst{
 | 
			
		||||
        .cbuf{addr},
 | 
			
		||||
        .inst{&inst},
 | 
			
		||||
        .block{block},
 | 
			
		||||
        .inst = &inst,
 | 
			
		||||
        .block = block,
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -211,7 +211,7 @@ void TexturePass(Environment& env, IR::Program& program) {
 | 
			
		||||
 | 
			
		||||
        const auto& cbuf{texture_inst.cbuf};
 | 
			
		||||
        auto flags{inst->Flags<IR::TextureInstInfo>()};
 | 
			
		||||
        switch (inst->Opcode()) {
 | 
			
		||||
        switch (inst->GetOpcode()) {
 | 
			
		||||
        case IR::Opcode::ImageQueryDimensions:
 | 
			
		||||
            flags.type.Assign(env.ReadTextureType(cbuf.index, cbuf.offset));
 | 
			
		||||
            inst->SetFlags(flags);
 | 
			
		||||
@@ -235,16 +235,16 @@ void TexturePass(Environment& env, IR::Program& program) {
 | 
			
		||||
        u32 index;
 | 
			
		||||
        if (flags.type == TextureType::Buffer) {
 | 
			
		||||
            index = descriptors.Add(TextureBufferDescriptor{
 | 
			
		||||
                .cbuf_index{cbuf.index},
 | 
			
		||||
                .cbuf_offset{cbuf.offset},
 | 
			
		||||
                .count{1},
 | 
			
		||||
                .cbuf_index = cbuf.index,
 | 
			
		||||
                .cbuf_offset = cbuf.offset,
 | 
			
		||||
                .count = 1,
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            index = descriptors.Add(TextureDescriptor{
 | 
			
		||||
                .type{flags.type},
 | 
			
		||||
                .cbuf_index{cbuf.index},
 | 
			
		||||
                .cbuf_offset{cbuf.offset},
 | 
			
		||||
                .count{1},
 | 
			
		||||
                .type = flags.type,
 | 
			
		||||
                .cbuf_index = cbuf.index,
 | 
			
		||||
                .cbuf_offset = cbuf.offset,
 | 
			
		||||
                .count = 1,
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        inst->SetArg(0, IR::Value{index});
 | 
			
		||||
 
 | 
			
		||||
@@ -14,14 +14,14 @@ namespace Shader::Optimization {
 | 
			
		||||
static void ValidateTypes(const IR::Program& program) {
 | 
			
		||||
    for (const auto& block : program.blocks) {
 | 
			
		||||
        for (const IR::Inst& inst : *block) {
 | 
			
		||||
            if (inst.Opcode() == IR::Opcode::Phi) {
 | 
			
		||||
            if (inst.GetOpcode() == IR::Opcode::Phi) {
 | 
			
		||||
                // Skip validation on phi nodes
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            const size_t num_args{inst.NumArgs()};
 | 
			
		||||
            for (size_t i = 0; i < num_args; ++i) {
 | 
			
		||||
                const IR::Type t1{inst.Arg(i).Type()};
 | 
			
		||||
                const IR::Type t2{IR::ArgTypeOf(inst.Opcode(), i)};
 | 
			
		||||
                const IR::Type t2{IR::ArgTypeOf(inst.GetOpcode(), i)};
 | 
			
		||||
                if (!IR::AreTypesCompatible(t1, t2)) {
 | 
			
		||||
                    throw LogicError("Invalid types in block:\n{}", IR::DumpBlock(*block));
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user