diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index eb412d08e3..4bbd1e133e 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -240,6 +243,7 @@ add_library(shader_recompiler STATIC runtime_info.h shader_info.h varying_state.h + frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h ) if (YUZU_USE_EXTERNAL_VULKAN_SPIRV_TOOLS) diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp index b0ebc75f7d..49e722e0fa 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -268,4 +271,40 @@ void TranslatorVisitor::ResetOFlag() { SetOFlag(ir.Imm1(false)); } +IR::U32 TranslatorVisitor::apply_ISBERD_shift(IR::U32 result, isberd::Shift shift_value) { + if (shift_value != isberd::Shift::Default) { + return ir.ShiftLeftLogical(result, ir.Imm32(1)); + } + return result; +} + +IR::U32 TranslatorVisitor::apply_ISBERD_size_read(IR::U32 address, isberd::SZ sz) { + switch (sz) { + case isberd::SZ::U8: + return ir.LoadGlobalU8(ir.UConvert(64, address)); + case isberd::SZ::U16: + return ir.LoadGlobalU16(ir.UConvert(64, address)); + case isberd::SZ::U32: + case isberd::SZ::F32: + return ir.LoadGlobal32(ir.UConvert(64, address)); + default: + UNREACHABLE(); + } +} + +IR::U32 TranslatorVisitor::compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value) { + IR::U32 address{}; + if (src_reg_num == 0xFF) { + address = ir.Imm32(imm); + } else { + auto offset = ir.Imm32(imm); + address = ir.IAdd(X(src_reg), offset); + if (skew_value != 0) { + address = ir.IAdd(address, ir.LaneId()); + } + } + + return address; +}; + } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h index adf7cad068..b901b3a8b9 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/impl.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -7,6 +10,7 @@ #include "shader_recompiler/frontend/ir/basic_block.h" #include "shader_recompiler/frontend/ir/ir_emitter.h" #include "shader_recompiler/frontend/maxwell/instruction.h" +#include "shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h" namespace Shader::Maxwell { @@ -381,6 +385,11 @@ public: void ResetSFlag(); void ResetCFlag(); void ResetOFlag(); + + // Helper functions for various translator visitors + IR::U32 apply_ISBERD_shift(IR::U32 result, isberd::Shift shift_value); + IR::U32 apply_ISBERD_size_read(IR::U32 address, isberd::SZ sz_value); + IR::U32 compute_ISBERD_address(IR::Reg src_reg, u32 src_reg_num, u32 imm, u64 skew_value); }; } // namespace Shader::Maxwell 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..43f4729b72 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 @@ -7,23 +7,9 @@ #include "common/bit_field.h" #include "common/common_types.h" #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" +#include "shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h" namespace Shader::Maxwell { -namespace { -enum class Mode : u64 { - Default, - Patch, - Prim, - Attr, -}; - -enum class Shift : u64 { - Default, - U16, - B32, -}; - -} // Anonymous namespace // Valid only for GS, TI, VS and trap void TranslatorVisitor::ISBERD(u64 insn) { @@ -35,70 +21,49 @@ void TranslatorVisitor::ISBERD(u64 insn) { BitField<24, 8, u32> imm; BitField<31, 1, u64> skew; BitField<32, 1, u64> o; - BitField<33, 2, Mode> mode; - BitField<47, 2, Shift> shift; + BitField<33, 2, isberd::Mode> mode; + BitField<36, 4, isberd::SZ> sz; + BitField<47, 2, isberd::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); - } + auto address = compute_ISBERD_address(isberd.src_reg, isberd.src_reg_num, isberd.imm, isberd.skew); 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); - } - X(isberd.dest_reg, ir.BitCast(result)); + auto result = apply_ISBERD_size_read(address, isberd.sz.Value()); + X(isberd.dest_reg, apply_ISBERD_shift(result, isberd.shift.Value())); + + return; } - if (isberd.mode != Mode::Default) { - IR::F32 result{}; - 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.mode != isberd::Mode::Default) { + IR::F32 result_f32{}; + switch (isberd.mode.Value()) { + case isberd::Mode::Patch: + result_f32 = ir.GetPatch(address.Patch()); + break; + case isberd::Mode::Prim: + result_f32 = ir.GetAttribute(address.Attribute()); + break; + case isberd::Mode::Attr: + result_f32 = ir.GetAttributeIndexed(address); + break; + default: + UNREACHABLE(); } - switch (static_cast(isberd.mode.Value())) { - case static_cast(Mode::Patch): - result = ir.GetPatch(index.Patch()); - break; - case static_cast(Mode::Prim): - result = ir.GetAttribute(index.Attribute()); - break; - case static_cast(Mode::Attr): - result = ir.GetAttributeIndexed(index); - break; - } - X(isberd.dest_reg, ir.BitCast(result)); + auto result_u32 = ir.BitCast(result_f32); + X(isberd.dest_reg, apply_ISBERD_shift(result_u32, isberd.shift.Value())); + return; } - 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; - } + + if (isberd.skew != 0) { + auto result = ir.IAdd(X(isberd.src_reg), ir.LaneId()); X(isberd.dest_reg, result); + + return; } - //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)}; - X(isberd.dest_reg, result); - } else { - X(isberd.dest_reg, X(isberd.src_reg)); - } + + // Fallback if nothing else applies + X(isberd.dest_reg, X(isberd.src_reg)); } } // namespace Shader::Maxwell diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h new file mode 100644 index 0000000000..ead0f7efe8 --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/internal_stage_buffer_entry_read.h @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once +#include "shader_recompiler/environment.h" +#include "shader_recompiler/frontend/ir/basic_block.h" +#include "shader_recompiler/frontend/ir/ir_emitter.h" +#include "shader_recompiler/frontend/maxwell/instruction.h" + +namespace Shader::Maxwell { +namespace isberd { +enum class Mode : u64 { + Default, + Patch, + Prim, + Attr, +}; + +enum class Shift : u64 { + Default, + U16, + B32, +}; + +enum class SZ : u64 { + U8, + U16, + U32, + F32, +}; + +} // Anonymous namespace + +} // namespace Shader::Maxwell diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 7e40e79d8e..973e5613d3 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +# SPDX-License-Identifier: GPL-3.0-or-later + # SPDX-FileCopyrightText: 2018 yuzu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later @@ -408,4 +411,4 @@ if (ARCHITECTURE_arm64) target_link_libraries(video_core PRIVATE sse2neon) endif() -create_target_directory_groups(video_core) +create_target_directory_groups(video_core) \ No newline at end of file