mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 19:36:55 +02:00
shader: execute PS5 BVH intersections and local FLAT stacks
Co-authored-by: Ali Almohaya <AliAlmohaya@gmail.com> Co-authored-by: Mac <me@itsmemac.com> Co-authored-by: Senaxx <michelbeld@gmail.com> Co-authored-by: Jean-Philippe <github@meunier.jp>
This commit is contained in:
@@ -225,6 +225,7 @@ Opcode DecodeMimgOpcode(uint32_t opcode, const MimgSampleInfo* sample, const Mim
|
||||
case 0x09u: return Opcode::IMAGE_STORE_MIP;
|
||||
case 0x0eu: return Opcode::IMAGE_GET_RESINFO;
|
||||
case 0x60u: return Opcode::IMAGE_GET_LOD;
|
||||
case 0xe6u: return Opcode::IMAGE_BVH_INTERSECT_RAY;
|
||||
default: return Opcode::UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
@@ -253,6 +254,7 @@ uint32_t DecodeMimgAddressComponents(uint32_t opcode, ImageDimension dimension,
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case 0xe6u: return 11u;
|
||||
case 0x0eu: return 1u;
|
||||
case 0x01u:
|
||||
case 0x09u: return ImageCoordComponents(dimension) + 1u;
|
||||
@@ -360,6 +362,11 @@ void DecodeMimg(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
||||
if (d16 && !supports_d16) {
|
||||
SetUnsupported(inst, Family::MIMG, opcode, "MIMG opcode does not support D16 data");
|
||||
}
|
||||
if (opcode == 0xe6u &&
|
||||
(a16 || !r128 || inst.dmask != 0xfu || (nsa_dwords != 0u && nsa_dwords != 3u))) {
|
||||
SetUnsupported(inst, Family::MIMG, opcode,
|
||||
"BVH intersection requires eleven full-float ray DWORDs and R128/dmask:0xf");
|
||||
}
|
||||
|
||||
DecodeVectorGpr(vdata, inst.dst);
|
||||
DecodeVectorGpr(vaddr, inst.src0);
|
||||
|
||||
@@ -254,6 +254,8 @@ void DecodeScalarSource(uint32_t code, uint32_t pc, Operand& operand) {
|
||||
case 125u: operand.kind = OperandKind::Null; return;
|
||||
case 126u: operand.kind = OperandKind::ExecLo; return;
|
||||
case 127u: operand.kind = OperandKind::ExecHi; return;
|
||||
case 235u: operand.kind = OperandKind::SharedBase; return;
|
||||
case 237u: operand.kind = OperandKind::PrivateBase; return;
|
||||
case 239u: operand.kind = OperandKind::PopsExitingWaveId; return;
|
||||
case 248u:
|
||||
operand.kind = OperandKind::FloatInlineConstant;
|
||||
@@ -404,7 +406,6 @@ void DecodeProgram(std::span<const uint32_t> code, Program& program) {
|
||||
program.instructions.clear();
|
||||
program.instructions.reserve(code.size());
|
||||
program.code = code;
|
||||
program.has_bvh = false;
|
||||
|
||||
std::vector<bool> branch_targets;
|
||||
for (uint32_t word_index = 0; word_index < code.size();) {
|
||||
@@ -413,10 +414,6 @@ void DecodeProgram(std::span<const uint32_t> code, Program& program) {
|
||||
|
||||
const auto& inst = program.instructions.back();
|
||||
word_index += inst.word_count;
|
||||
if (inst.family == Family::MIMG && (inst.opcode_id == 0xe6u || inst.opcode_id == 0xe7u)) {
|
||||
program.has_bvh = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsDirectBranch(inst.opcode)) {
|
||||
const auto target_index = inst.branch_target / sizeof(uint32_t);
|
||||
@@ -455,6 +452,8 @@ std::string OperandToString(const Operand& operand) {
|
||||
case OperandKind::Scc: text = "scc"; break;
|
||||
case OperandKind::M0: text = "m0"; break;
|
||||
case OperandKind::PopsExitingWaveId: text = "pops_exiting_wave_id"; break;
|
||||
case OperandKind::SharedBase: text = "shared_base"; break;
|
||||
case OperandKind::PrivateBase: text = "private_base"; break;
|
||||
case OperandKind::Null: text = "null"; break;
|
||||
default: text = "unknown"; break;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
|
||||
namespace Libs::Graphics::ShaderRecompiler::Decoder {
|
||||
|
||||
// PS5 flat stack addresses use these SH_MEM_BASES aperture tags in VA[63:32].
|
||||
constexpr uint32_t PrivateApertureHigh = 0x70000000u;
|
||||
constexpr uint32_t SharedApertureHigh = 0x80000000u;
|
||||
|
||||
enum class Family {
|
||||
Unknown,
|
||||
SOP1,
|
||||
@@ -569,6 +573,7 @@ enum class Opcode {
|
||||
DS_WRITE_B128,
|
||||
DS_WRITE_ADDTID_B32,
|
||||
DS_READ_ADDTID_B32,
|
||||
IMAGE_BVH_INTERSECT_RAY,
|
||||
IMAGE_GET_RESINFO,
|
||||
IMAGE_GET_LOD,
|
||||
IMAGE_LOAD,
|
||||
@@ -636,6 +641,8 @@ enum class OperandKind {
|
||||
Scc,
|
||||
M0,
|
||||
PopsExitingWaveId,
|
||||
SharedBase,
|
||||
PrivateBase,
|
||||
Null,
|
||||
Vgpr,
|
||||
};
|
||||
@@ -747,7 +754,6 @@ struct Instruction {
|
||||
struct Program {
|
||||
std::span<const uint32_t> code;
|
||||
std::vector<Instruction> instructions;
|
||||
bool has_bvh = false;
|
||||
};
|
||||
|
||||
// Code spans are trusted to contain complete instructions, valid branch targets, and 32-bit PCs.
|
||||
|
||||
@@ -883,6 +883,15 @@ void Translator::DS_BPERMUTE_B32(const Decoder::Instruction& inst) {
|
||||
|
||||
void Translator::EmitMemory(const Decoder::Instruction& inst) {
|
||||
switch (inst.opcode) {
|
||||
case Decoder::Opcode::IMAGE_BVH_INTERSECT_RAY: {
|
||||
const auto result = ir.Emit(IR::ValueOpcode::BvhIntersect,
|
||||
{ConstructU32x4(inst.src1, 4), MakeImageAddress(inst, inst.src0), ir.GetExec()});
|
||||
for (uint32_t component = 0; component < 4; ++component) {
|
||||
WriteOperand(OffsetOperand(inst.dst, component),
|
||||
ir.Emit(IR::ValueOpcode::CompositeExtractU32x4, {result, IR::Value(component)}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
case Decoder::Opcode::S_LOAD_DWORD:
|
||||
case Decoder::Opcode::S_LOAD_DWORDX2:
|
||||
case Decoder::Opcode::S_LOAD_DWORDX4:
|
||||
|
||||
@@ -135,6 +135,8 @@ IR::U32 Translator::ReadRawU32(const Decoder::Operand& operand) {
|
||||
case Decoder::OperandKind::IntegerInlineConstant:
|
||||
case Decoder::OperandKind::FloatInlineConstant: return IR::U32(IR::Value(operand.value));
|
||||
case Decoder::OperandKind::Null:
|
||||
case Decoder::OperandKind::SharedBase:
|
||||
case Decoder::OperandKind::PrivateBase:
|
||||
case Decoder::OperandKind::PopsExitingWaveId: return IR::U32(IR::Value(0u));
|
||||
case Decoder::OperandKind::Sgpr:
|
||||
return ir.GetScalarReg(static_cast<IR::ScalarReg>(operand.reg));
|
||||
@@ -474,6 +476,12 @@ IR::U32 Translator::ReadU32(const Decoder::Operand& operand) {
|
||||
}
|
||||
|
||||
std::array<IR::U32, 2> Translator::ReadU32Pair(const Decoder::Operand& operand) {
|
||||
if (operand.kind == Decoder::OperandKind::PrivateBase ||
|
||||
operand.kind == Decoder::OperandKind::SharedBase) {
|
||||
return {IR::U32(IR::Value(0u)), IR::U32(IR::Value(
|
||||
operand.kind == Decoder::OperandKind::PrivateBase ? Decoder::PrivateApertureHigh
|
||||
: Decoder::SharedApertureHigh))};
|
||||
}
|
||||
if (operand.kind == Decoder::OperandKind::ExecLo) {
|
||||
return {ir.GetExecLo(), ir.GetExecHi()};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user