eden/src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp
JPikachu 91a662431c [Texture_cache] Better memory handling for devices with lower memory allocations (#233)
Means games like Minecraft Dungeons, Sea of Stars, Luigi Mansion 2, Astroneer, Alan Wake, etc are now playable.
It also cleans up the recent abi.cpp and bindless texture commits a bit.
Everything is in #ifdef ANDROID - The biggest change is CACHING_PAGEBITS = 12.
Without that the way the buffercache grows and joins buffers can cause Android to run out of memory (as you end up with just one big buffer that needs to be copied every time it grows)
Also patches up ffmpeg issues.

Reviewed-on: eden-emu/eden#233
Co-authored-by: JPikachu <jpikachu.eden@gmail.com>
Co-committed-by: JPikachu <jpikachu.eden@gmail.com>
2025-06-29 17:14:23 +00:00

81 lines
2.7 KiB
C++

// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/bit_field.h"
#include "common/common_types.h"
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
#include <fstream>
namespace Shader::Maxwell {
namespace {
enum class ShuffleMode : u64 {
IDX,
UP,
DOWN,
BFLY,
};
[[nodiscard]] IR::U32 ShuffleOperation(IR::IREmitter& ir, const IR::U32& value,
const IR::U32& index, const IR::U32& mask,
ShuffleMode shfl_op) {
const IR::U32 clamp{ir.BitFieldExtract(mask, ir.Imm32(0), ir.Imm32(5))};
const IR::U32 seg_mask{ir.BitFieldExtract(mask, ir.Imm32(8), ir.Imm32(5))};
switch (shfl_op) {
case ShuffleMode::IDX:
return ir.ShuffleIndex(value, index, clamp, seg_mask);
case ShuffleMode::UP:
return ir.ShuffleUp(value, index, clamp, seg_mask);
case ShuffleMode::DOWN:
return ir.ShuffleDown(value, index, clamp, seg_mask);
case ShuffleMode::BFLY:
return ir.ShuffleButterfly(value, index, clamp, seg_mask);
default:
throw NotImplementedException("Invalid SHFL op {}", shfl_op);
}
}
bool IsKONA() {
std::ifstream machineFile("/sys/devices/soc0/machine");
if (machineFile.is_open()) {
std::string line;
std::getline(machineFile, line);
if (line == "KONA")
return true;
}
return false;
}
void Shuffle(TranslatorVisitor& v, u64 insn, const IR::U32& index, const IR::U32& mask) {
union {
u64 insn;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 8, IR::Reg> src_reg;
BitField<30, 2, ShuffleMode> mode;
BitField<48, 3, IR::Pred> pred;
} const shfl{insn};
const IR::U32 result{ShuffleOperation(v.ir, v.X(shfl.src_reg), index, mask, shfl.mode)};
v.ir.SetPred(shfl.pred, v.ir.GetInBoundsFromOp(result));
if (IsKONA())
v.X(shfl.dest_reg, v.ir.Imm32(0xffffffff)); // This fixes the freeze for Retroid / Snapdragon SD865
else
v.X(shfl.dest_reg, result);
}
} // Anonymous namespace
void TranslatorVisitor::SHFL(u64 insn) {
union {
u64 insn;
BitField<20, 5, u64> src_a_imm;
BitField<28, 1, u64> src_a_flag;
BitField<29, 1, u64> src_b_flag;
BitField<34, 13, u64> src_b_imm;
} const flags{insn};
const IR::U32 src_a{flags.src_a_flag != 0 ? ir.Imm32(static_cast<u32>(flags.src_a_imm))
: GetReg20(insn)};
const IR::U32 src_b{flags.src_b_flag != 0 ? ir.Imm32(static_cast<u32>(flags.src_b_imm))
: GetReg39(insn)};
Shuffle(*this, insn, src_a, src_b);
}
} // namespace Shader::Maxwell