mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-30 17:18:14 +00:00
shader: lower whole-wave OR scans to subgroup reductions
This commit is contained in:
1 parent
eb3cb47296
commit
0c2546e850
8 files changed
+80
-41
No files matched your search
@@ -859,6 +859,10 @@ uint32_t EmitSubgroupUMaxU32(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
return EmitSubgroupReduceU32<spv::OpGroupNonUniformUMax, EmitUMax32>(ctx, inst);
|
||||
}
|
||||
|
||||
uint32_t EmitSubgroupOrU32(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
return EmitSubgroupReduceU32<spv::OpGroupNonUniformBitwiseOr, EmitOrU32>(ctx, inst);
|
||||
}
|
||||
|
||||
uint32_t EmitWriteLane(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
auto& state = ctx.state;
|
||||
const auto hit = state.builder.AllocateId();
|
||||
|
||||
@@ -236,6 +236,7 @@ uint32_t EmitReadFirstLane(ValueEmitContext& ctx, const IR::Inst& i
|
||||
uint32_t EmitReadLane(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitSubgroupUMinU32(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitSubgroupUMaxU32(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitSubgroupOrU32(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitWriteLane(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitPermlane16U32(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
uint32_t EmitGetAttribute(ValueEmitContext& ctx, const IR::Inst& inst);
|
||||
|
||||
@@ -235,7 +235,8 @@ void EmitDirectInstruction(ValueEmitContext& ctx, const IR::Inst& inst) {
|
||||
const auto op = inst.GetOpcode();
|
||||
if (ctx.half != 0 &&
|
||||
(op == Op::Ballot || op == Op::ReadFirstLane || op == Op::SubgroupUMinU32 ||
|
||||
op == Op::SubgroupUMaxU32 || op == Op::ReadConstBuffer || op == Op::ReadRealtimeClock ||
|
||||
op == Op::SubgroupUMaxU32 || op == Op::SubgroupOrU32 || op == Op::ReadConstBuffer ||
|
||||
op == Op::ReadRealtimeClock ||
|
||||
(op == Op::LoadAddressU32 && ctx.Memory(inst).kind == IR::ResourceKind::ScalarAddress))) {
|
||||
// Whole-wave results, clocks and SMEM loads (SGPR operands, no EXEC) match in both halves.
|
||||
ctx.Define(inst, ctx.other_half->Result(inst));
|
||||
|
||||
@@ -224,6 +224,7 @@ VALUE_OPCODE(ReadFirstLane, U32, U32, U1)
|
||||
VALUE_OPCODE(ReadLane, U32, U32, U32)
|
||||
VALUE_OPCODE(SubgroupUMinU32, U32, U32)
|
||||
VALUE_OPCODE(SubgroupUMaxU32, U32, U32)
|
||||
VALUE_OPCODE(SubgroupOrU32, U32, U32)
|
||||
VALUE_OPCODE(WriteLane, U32, U32, U32, U32)
|
||||
VALUE_OPCODE(Permlane16U32, U32, U32, U32, U32, U1, U32)
|
||||
VALUE_OPCODE(PermuteU32, U32, U32, U32, U1)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "graphics/shader/recompiler/ir/passes/ReadLaneElimination.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <optional>
|
||||
#include <queue>
|
||||
|
||||
#include <unordered_map>
|
||||
@@ -186,6 +186,16 @@ private:
|
||||
ValueOpcode operation;
|
||||
};
|
||||
|
||||
// The subgroup reduction that replaces a proven whole-wave scan of operation.
|
||||
std::optional<ValueOpcode> WaveReduction(ValueOpcode operation) {
|
||||
switch (operation) {
|
||||
case ValueOpcode::UMin32: return ValueOpcode::SubgroupUMinU32;
|
||||
case ValueOpcode::UMax32: return ValueOpcode::SubgroupUMaxU32;
|
||||
case ValueOpcode::BitwiseOr32: return ValueOpcode::SubgroupOrU32;
|
||||
default: return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ReadLaneStats EliminateReadLane(Program& program, uint32_t wave_size) {
|
||||
@@ -197,15 +207,12 @@ ReadLaneStats EliminateReadLane(Program& program, uint32_t wave_size) {
|
||||
for (auto* block: program.blocks) {
|
||||
for (auto& inst: *block) {
|
||||
const auto opcode = inst.GetOpcode();
|
||||
if (opcode == ValueOpcode::UMin32 || opcode == ValueOpcode::UMax32) {
|
||||
if (const auto reduce = WaveReduction(opcode)) {
|
||||
const auto seed = WaveReductionMatcher(block, opcode).Match(inst, wave_size);
|
||||
if (!seed.IsEmpty()) {
|
||||
const auto position = std::find_if(block->begin(), block->end(),
|
||||
[&](const Inst& candidate) { return &candidate == &inst; });
|
||||
const auto reduce = opcode == ValueOpcode::UMin32
|
||||
? ValueOpcode::SubgroupUMinU32
|
||||
: ValueOpcode::SubgroupUMaxU32;
|
||||
auto& reduction = *block->PrependNewInst(position, reduce, {seed});
|
||||
auto& reduction = *block->PrependNewInst(position, *reduce, {seed});
|
||||
inst.ReplaceUsesWith(Value(&reduction));
|
||||
stats.rewritten_reductions++;
|
||||
}
|
||||
|
||||
@@ -524,7 +524,8 @@ void Visit(Program& program, ShaderStageInputInfo input_info, InputUsage& inputs
|
||||
case ValueOpcode::Ballot: info.subgroup_ballot = true; break;
|
||||
case ValueOpcode::LiveMask: info.subgroup_ballot = info.helper_invocation = true; break;
|
||||
case ValueOpcode::SubgroupUMinU32:
|
||||
case ValueOpcode::SubgroupUMaxU32: info.subgroup_arithmetic = true; break;
|
||||
case ValueOpcode::SubgroupUMaxU32:
|
||||
case ValueOpcode::SubgroupOrU32: info.subgroup_arithmetic = true; break;
|
||||
case ValueOpcode::DppMoveU32:
|
||||
case ValueOpcode::ReadFirstLane:
|
||||
case ValueOpcode::ReadLane: {
|
||||
|
||||
Reference in new issue
Block a user