From d63b68f357a474be3dae186dd444a9ab94a44eb6 Mon Sep 17 00:00:00 2001 From: SDK Chan Date: Sun, 3 Aug 2025 18:09:19 +0000 Subject: [PATCH 1/3] [shader_recompiler/Maxwell] Rewrite ISBERD and fix potential downsides --- .../impl/internal_stage_buffer_entry_read.cpp | 84 +++++++++++-------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp index d71c65069b..3889157905 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp @@ -10,6 +10,7 @@ namespace Shader::Maxwell { namespace { + enum class Mode : u64 { Default, Patch, @@ -39,65 +40,76 @@ void TranslatorVisitor::ISBERD(u64 insn) { BitField<47, 2, Shift> shift; } const isberd{insn}; - if (isberd.skew != 0) { - IR::U32 current_lane_id{ir.LaneId()}; - IR::U32 result{ir.IAdd(X(isberd.src_reg), current_lane_id)}; - X(isberd.dest_reg, result); - } + bool is_only_skew_op = true; + auto apply_shift = [&](IR::U32 result) -> IR::U32 { + switch (isberd.shift.Value()) { + case Shift::U16: + case Shift::B32: + return ir.ShiftLeftLogical(result, ir.Imm32(1)); + default: + return result; + } + }; + if (isberd.o != 0) { IR::U32 address{}; - IR::F32 result{}; if (isberd.src_reg_num == 0xFF) { address = ir.Imm32(isberd.imm); - result = ir.GetAttributeIndexed(address); } else { IR::U32 offset = ir.Imm32(isberd.imm); address = ir.IAdd(X(isberd.src_reg), offset); - result = ir.GetAttributeIndexed(address); + if (isberd.skew != 0) { + address = ir.IAdd(address, ir.LaneId()); + } } - X(isberd.dest_reg, ir.BitCast(result)); + + IR::U32 result = ir.BitCast(ir.GetAttributeIndexed(address)); + if (isberd.shift != Shift::Default) { + result = apply_shift(result); + } + + is_only_skew_op = false; + X(isberd.dest_reg, result); } - if (isberd.mode != Mode::Default) { - IR::F32 result{}; + + else if (isberd.mode != Mode::Default) { IR::U32 index{}; if (isberd.src_reg_num == 0xFF) { index = ir.Imm32(isberd.imm); } else { index = ir.IAdd(X(isberd.src_reg), ir.Imm32(isberd.imm)); + if (isberd.skew != 0) { + index = ir.IAdd(index, ir.LaneId()); + } } - switch (static_cast(isberd.mode.Value())) { - case static_cast(Mode::Patch): - result = ir.GetPatch(index.Patch()); + IR::F32 result_f32{}; + switch (isberd.mode.Value()) { + case Mode::Patch: + result_f32 = ir.GetPatch(index.Patch()); break; - case static_cast(Mode::Prim): - result = ir.GetAttribute(index.Attribute()); + case Mode::Prim: + result_f32 = ir.GetAttribute(index.Attribute()); break; - case static_cast(Mode::Attr): - result = ir.GetAttributeIndexed(index); + case Mode::Attr: + result_f32 = ir.GetAttributeIndexed(index); + break; + default: break; } - X(isberd.dest_reg, ir.BitCast(result)); - } - if (isberd.shift != Shift::Default) { - IR::U32 result{}; - switch (static_cast(isberd.shift.Value())) { - case static_cast(Shift::U16): - result = ir.ShiftLeftLogical(result, static_cast(ir.Imm16(1))); - break; - case static_cast(Shift::B32): - result = ir.ShiftLeftLogical(result, ir.Imm32(1)); - break; + + IR::U32 result_u32 = ir.BitCast(result_f32); + if (isberd.shift != Shift::Default) { + result_u32 = apply_shift(result_u32); } - X(isberd.dest_reg, result); + + is_only_skew_op = false; + X(isberd.dest_reg, result_u32); } - //LOG_DEBUG(Shader, "(STUBBED) called {}", insn); - if (isberd.src_reg_num == 0xFF) { - IR::U32 src_imm{ir.Imm32(static_cast(isberd.imm))}; - IR::U32 result{ir.IAdd(X(isberd.src_reg), src_imm)}; + + if (isberd.skew != 0 && is_only_skew_op) { + IR::U32 result = ir.IAdd(X(isberd.src_reg), ir.LaneId()); X(isberd.dest_reg, result); - } else { - X(isberd.dest_reg, X(isberd.src_reg)); } } -- 2.39.5 From 7323ffeb458a09e39055bc39eb5a37a0b3744ced Mon Sep 17 00:00:00 2001 From: SDK-Chan Date: Mon, 4 Aug 2025 11:26:44 +0200 Subject: [PATCH 2/3] Update src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp Forgot to add the fallback if everything else in ISBERD results do default. --- .../translate/impl/internal_stage_buffer_entry_read.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp index 3889157905..f879cfdee5 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp @@ -110,7 +110,9 @@ void TranslatorVisitor::ISBERD(u64 insn) { if (isberd.skew != 0 && is_only_skew_op) { IR::U32 result = ir.IAdd(X(isberd.src_reg), ir.LaneId()); X(isberd.dest_reg, result); - } + } else { + X(isberd.dest_reg, X(isberd.src_reg)); + } } } // namespace Shader::Maxwell -- 2.39.5 From ccbd4f4bfd6e7ac16e85a14f029962fd5894c224 Mon Sep 17 00:00:00 2001 From: SDK-Chan Date: Mon, 4 Aug 2025 11:31:20 +0200 Subject: [PATCH 3/3] Update src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp --- .../translate/impl/internal_stage_buffer_entry_read.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp index f879cfdee5..1ef87e10ea 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.cpp @@ -41,6 +41,7 @@ void TranslatorVisitor::ISBERD(u64 insn) { } const isberd{insn}; bool is_only_skew_op = true; + bool no_other_op = true; auto apply_shift = [&](IR::U32 result) -> IR::U32 { switch (isberd.shift.Value()) { case Shift::U16: @@ -69,6 +70,7 @@ void TranslatorVisitor::ISBERD(u64 insn) { } is_only_skew_op = false; + no_other_op = false; X(isberd.dest_reg, result); } @@ -104,13 +106,14 @@ void TranslatorVisitor::ISBERD(u64 insn) { } is_only_skew_op = false; + no_other_op = false; X(isberd.dest_reg, result_u32); } if (isberd.skew != 0 && is_only_skew_op) { IR::U32 result = ir.IAdd(X(isberd.src_reg), ir.LaneId()); X(isberd.dest_reg, result); - } else { + } else if (no_other_op) { X(isberd.dest_reg, X(isberd.src_reg)); } } -- 2.39.5