Files
eden/src/shader_recompiler/ir_opt/compaction_fallback_pass.cpp
T

72 lines
2.3 KiB
C++

// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "shader_recompiler/frontend/ir/ir_emitter.h"
#include "shader_recompiler/host_translate_info.h"
#include "shader_recompiler/ir_opt/passes.h"
namespace Shader::Optimization {
namespace {
constexpr int MAX_BALLOT_SEARCH_DEPTH = 8;
bool DependsOnSubgroupBallot(const IR::Value& value, int depth) {
if (depth > MAX_BALLOT_SEARCH_DEPTH || value.IsImmediate()) {
return false;
}
IR::Inst* const producer{value.Inst()};
if (producer->GetOpcode() == IR::Opcode::SubgroupBallot) {
return true;
}
if (producer->GetOpcode() == IR::Opcode::Phi) {
return false;
}
const size_t num_args{producer->NumArgs()};
for (size_t index = 0; index < num_args; ++index) {
if (DependsOnSubgroupBallot(producer->Arg(index), depth + 1)) {
return true;
}
}
return false;
}
void RewriteAtomic(IR::Block& block, IR::Inst& inst) {
const auto insert_point{IR::Block::InstructionList::s_iterator_to(inst)};
IR::IREmitter ir{block, insert_point};
const IR::U32 amount{inst.Arg(2)};
const IR::U32 primitive_id{ir.GetAttributeU32(IR::Attribute::PrimitiveId)};
const IR::U1 reserves_slot{ir.INotEqual(amount, ir.Imm32(0u))};
const IR::U32 slot_end{ir.IAdd(primitive_id, ir.Imm32(1u))};
const IR::U32 high_water{IR::U32{ir.Select(reserves_slot, slot_end, ir.Imm32(0u))}};
block.PrependNewInst(insert_point, IR::Opcode::StorageAtomicUMax32,
{inst.Arg(0), inst.Arg(1), high_water});
inst.ReplaceUsesWith(primitive_id);
}
} // Anonymous namespace
void CompactionFallbackPass(IR::Program& program, const HostTranslateInfo& host_info) {
if (program.stage != Stage::Geometry || host_info.support_subgroup_in_geometry_stage) {
return;
}
for (IR::Block* const block : program.post_order_blocks) {
for (IR::Inst& inst : block->Instructions()) {
if (inst.GetOpcode() != IR::Opcode::StorageAtomicIAdd32) {
continue;
}
if (!inst.HasUses()) {
continue;
}
if (!DependsOnSubgroupBallot(inst.Arg(2), 0)) {
continue;
}
RewriteAtomic(*block, inst);
}
}
}
} // namespace Shader::Optimization