From df57012c5023224fe2c19a7adf2ed9493d3dab3b Mon Sep 17 00:00:00 2001 From: Steveice10 <1269164+Steveice10@users.noreply.github.com> Date: Sat, 26 Aug 2023 15:49:31 -0700 Subject: [PATCH] video_core: Correct shader interpeter address register handling. (#6910) --- src/video_core/shader/shader_interpreter.cpp | 74 +++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/src/video_core/shader/shader_interpreter.cpp b/src/video_core/shader/shader_interpreter.cpp index cbdbfa2a8..324e1f07a 100644 --- a/src/video_core/shader/shader_interpreter.cpp +++ b/src/video_core/shader/shader_interpreter.cpp @@ -112,8 +112,9 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData const auto& swizzle_data = setup.swizzle_data; const auto& program_code = setup.program_code; - // Placeholder for invalid inputs - static f24 dummy_vec4_float24[4]; + // Constants for handling invalid inputs + static f24 dummy_vec4_float24_zeros[4] = {f24::Zero(), f24::Zero(), f24::Zero(), f24::Zero()}; + static f24 dummy_vec4_float24_ones[4] = {f24::One(), f24::One(), f24::One(), f24::One()}; u32 iteration = 0; bool should_stop = false; @@ -130,19 +131,33 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData debug_data.max_offset = std::max(debug_data.max_offset, 1 + program_counter); - auto LookupSourceRegister = [&](const SourceRegister& source_reg) -> const f24* { + auto LookupSourceRegister = [&](const SourceRegister& source_reg, + int address_register_index) -> const f24* { + int index = source_reg.GetIndex(); switch (source_reg.GetRegisterType()) { case RegisterType::Input: - return &state.registers.input[source_reg.GetIndex()].x; + return &state.registers.input[index].x; case RegisterType::Temporary: - return &state.registers.temporary[source_reg.GetIndex()].x; + return &state.registers.temporary[index].x; case RegisterType::FloatUniform: - return &uniforms.f[source_reg.GetIndex()].x; + if (address_register_index != 0) { + int offset = state.address_registers[address_register_index - 1]; + if (offset < std::numeric_limits::min() || + offset > std::numeric_limits::max()) [[unlikely]] { + offset = 0; + } + index = (index + offset) & 0x7F; + // If the index is above 96, the result is all one. + if (index >= 96) [[unlikely]] { + return dummy_vec4_float24_ones; + } + } + return &uniforms.f[index].x; default: - return dummy_vec4_float24; + return dummy_vec4_float24_zeros; } }; @@ -151,18 +166,15 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData const bool is_inverted = (0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed)); - const int address_offset = - (instr.common.address_register_index == 0) - ? 0 - : state.address_registers[instr.common.address_register_index - 1]; + const f24* src1_ = + LookupSourceRegister(instr.common.GetSrc1(is_inverted), + !is_inverted * instr.common.address_register_index); + const f24* src2_ = + LookupSourceRegister(instr.common.GetSrc2(is_inverted), + is_inverted * instr.common.address_register_index); - const f24* src1_ = LookupSourceRegister(instr.common.GetSrc1(is_inverted) + - (is_inverted ? 0 : address_offset)); - const f24* src2_ = LookupSourceRegister(instr.common.GetSrc2(is_inverted) + - (is_inverted ? address_offset : 0)); - - const bool negate_src1 = ((bool)swizzle.negate_src1 != false); - const bool negate_src2 = ((bool)swizzle.negate_src2 != false); + const bool negate_src1 = swizzle.negate_src1.Value() != 0; + const bool negate_src2 = swizzle.negate_src2.Value() != 0; f24 src1[4] = { src1_[(int)swizzle.src1_selector_0.Value()], @@ -193,7 +205,7 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData ? &state.registers.output[instr.common.dest.Value().GetIndex()][0] : (instr.common.dest.Value() < 0x20) ? &state.registers.temporary[instr.common.dest.Value().GetIndex()][0] - : dummy_vec4_float24; + : dummy_vec4_float24_zeros; debug_data.max_opdesc_id = std::max(debug_data.max_opdesc_id, 1 + instr.common.operand_desc_id); @@ -476,20 +488,16 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData bool is_inverted = (instr.opcode.Value().EffectiveOpCode() == OpCode::Id::MADI); - const int address_offset = - (instr.mad.address_register_index == 0) - ? 0 - : state.address_registers[instr.mad.address_register_index - 1]; + const f24* src1_ = LookupSourceRegister(instr.mad.GetSrc1(is_inverted), 0); + const f24* src2_ = + LookupSourceRegister(instr.mad.GetSrc2(is_inverted), + !is_inverted * instr.mad.address_register_index); + const f24* src3_ = LookupSourceRegister( + instr.mad.GetSrc3(is_inverted), is_inverted * instr.mad.address_register_index); - const f24* src1_ = LookupSourceRegister(instr.mad.GetSrc1(is_inverted)); - const f24* src2_ = LookupSourceRegister(instr.mad.GetSrc2(is_inverted) + - (!is_inverted * address_offset)); - const f24* src3_ = LookupSourceRegister(instr.mad.GetSrc3(is_inverted) + - (is_inverted * address_offset)); - - const bool negate_src1 = ((bool)mad_swizzle.negate_src1 != false); - const bool negate_src2 = ((bool)mad_swizzle.negate_src2 != false); - const bool negate_src3 = ((bool)mad_swizzle.negate_src3 != false); + const bool negate_src1 = mad_swizzle.negate_src1.Value() != 0; + const bool negate_src2 = mad_swizzle.negate_src2.Value() != 0; + const bool negate_src3 = mad_swizzle.negate_src3.Value() != 0; f24 src1[4] = { src1_[(int)mad_swizzle.src1_selector_0.Value()], @@ -532,7 +540,7 @@ static void RunInterpreter(const ShaderSetup& setup, UnitState& state, DebugData ? &state.registers.output[instr.mad.dest.Value().GetIndex()][0] : (instr.mad.dest.Value() < 0x20) ? &state.registers.temporary[instr.mad.dest.Value().GetIndex()][0] - : dummy_vec4_float24; + : dummy_vec4_float24_zeros; Record(debug_data, iteration, src1); Record(debug_data, iteration, src2);