From 0e9420a7b228f3e560ba154ad33e037358679638 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Thu, 5 Jun 2025 08:43:39 -0500 Subject: [PATCH 1/5] Fix request queues in libSceZlib (#3041) Queues are a FIFO data structure, so pop() removes the front, not the end. --- src/core/libraries/zlib/zlib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/zlib/zlib.cpp b/src/core/libraries/zlib/zlib.cpp index 899cb5bf6..b304992ad 100644 --- a/src/core/libraries/zlib/zlib.cpp +++ b/src/core/libraries/zlib/zlib.cpp @@ -51,7 +51,7 @@ void ZlibTaskThread(const std::stop_token& stop) { if (!task_queue_cv.wait(lock, stop, [&] { return !task_queue.empty(); })) { break; } - task = task_queue.back(); + task = task_queue.front(); task_queue.pop(); } @@ -136,7 +136,7 @@ s32 PS4_SYSV_ABI sceZlibWaitForDone(u64* request_id, const u32* timeout) { } else { done_queue_cv.wait(lock, pred); } - *request_id = done_queue.back(); + *request_id = done_queue.front(); done_queue.pop(); } return ORBIS_OK; From 3b3026ff1c98137e4f3051ec44c0eb4e1fa2f8ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Thu, 5 Jun 2025 15:44:02 +0200 Subject: [PATCH 2/5] [CI] Update Qt to 6.9.1 (#3037) --- .github/workflows/build.yml | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bb3d157b7..588236b14 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -76,18 +76,13 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{ runner.os }}-sdl-cache-cmake-build with: append-timestamp: false key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} - - name: Setup VS Environment - uses: ilammy/msvc-dev-cmd@v1.13.0 - with: - arch: amd64 - - name: Configure CMake run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache @@ -111,7 +106,7 @@ jobs: - name: Setup Qt uses: jurplel/install-qt-action@v4 with: - version: 6.9.0 + version: 6.9.1 host: windows target: desktop arch: win64_msvc2022_64 @@ -130,18 +125,13 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{ runner.os }}-qt-cache-cmake-build with: append-timestamp: false key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} - - name: Setup VS Environment - uses: ilammy/msvc-dev-cmd@v1.13.0 - with: - arch: amd64 - - name: Configure CMake run: cmake --fresh -G Ninja -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache @@ -186,7 +176,7 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{runner.os}}-sdl-cache-cmake-build with: @@ -228,7 +218,7 @@ jobs: - name: Setup Qt uses: jurplel/install-qt-action@v4 with: - version: 6.9.0 + version: 6.9.1 host: mac target: desktop arch: clang_64 @@ -247,7 +237,7 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{runner.os}}-qt-cache-cmake-build with: @@ -301,7 +291,7 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{ runner.os }}-sdl-cache-cmake-build with: @@ -362,7 +352,7 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{ runner.os }}-qt-cache-cmake-build with: @@ -409,7 +399,7 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build with: @@ -445,7 +435,7 @@ jobs: ${{ env.cache-name }}- - name: Cache CMake Build - uses: hendrikmuhs/ccache-action@v1.2.17 + uses: hendrikmuhs/ccache-action@v1.2.18 env: cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-build with: From 43bf4ed1bca1cd6442e97b04d9afb8383219bb86 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:14:34 -0500 Subject: [PATCH 3/5] sceVideoOutGetResolutionStatus error behavior (#3044) --- src/core/libraries/videoout/video_out.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/videoout/video_out.cpp b/src/core/libraries/videoout/video_out.cpp index c5208b6dd..da715b3bf 100644 --- a/src/core/libraries/videoout/video_out.cpp +++ b/src/core/libraries/videoout/video_out.cpp @@ -282,7 +282,12 @@ s32 PS4_SYSV_ABI sceVideoOutGetVblankStatus(int handle, SceVideoOutVblankStatus* s32 PS4_SYSV_ABI sceVideoOutGetResolutionStatus(s32 handle, SceVideoOutResolutionStatus* status) { LOG_INFO(Lib_VideoOut, "called"); - *status = driver->GetPort(handle)->resolution; + auto* port = driver->GetPort(handle); + if (!port || !port->is_open) { + return ORBIS_VIDEO_OUT_ERROR_INVALID_HANDLE; + } + + *status = port->resolution; return ORBIS_OK; } From fff3bf9917faef7a185cae896efce87bea7b5b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Thu, 5 Jun 2025 23:33:25 +0200 Subject: [PATCH 4/5] s_flbit_i32_b64 (#3033) * s_flbit_i32_b64 * Split FindUMsb64 into two 32bit ops --- .../backend/spirv/emit_spirv_instructions.h | 1 + .../backend/spirv/emit_spirv_integer.cpp | 14 ++++++++++++++ .../frontend/translate/scalar_alu.cpp | 13 +++++++++++++ .../frontend/translate/translate.h | 1 + src/shader_recompiler/ir/ir_emitter.cpp | 11 +++++++++-- src/shader_recompiler/ir/ir_emitter.h | 2 +- src/shader_recompiler/ir/opcodes.inc | 1 + 7 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 09f9732bf..172358866 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -372,6 +372,7 @@ Id EmitBitCount64(EmitContext& ctx, Id value); Id EmitBitwiseNot32(EmitContext& ctx, Id value); Id EmitFindSMsb32(EmitContext& ctx, Id value); Id EmitFindUMsb32(EmitContext& ctx, Id value); +Id EmitFindUMsb64(EmitContext& ctx, Id value); Id EmitFindILsb32(EmitContext& ctx, Id value); Id EmitFindILsb64(EmitContext& ctx, Id value); Id EmitSMin32(EmitContext& ctx, Id a, Id b); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp index 10bfbb2ab..1a995354d 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -229,6 +229,20 @@ Id EmitFindUMsb32(EmitContext& ctx, Id value) { return ctx.OpFindUMsb(ctx.U32[1], value); } +Id EmitFindUMsb64(EmitContext& ctx, Id value) { + // Vulkan restricts some bitwise operations to 32-bit only, so decompose into + // two 32-bit values and select the correct result. + const Id unpacked{ctx.OpBitcast(ctx.U32[2], value)}; + const Id hi{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 1U)}; + const Id lo{ctx.OpCompositeExtract(ctx.U32[1], unpacked, 0U)}; + const Id hi_msb{ctx.OpFindUMsb(ctx.U32[1], hi)}; + const Id lo_msb{ctx.OpFindUMsb(ctx.U32[1], lo)}; + const Id found_hi{ctx.OpINotEqual(ctx.U1[1], hi_msb, ctx.ConstU32(u32(-1)))}; + const Id shifted_hi{ctx.OpIAdd(ctx.U32[1], hi_msb, ctx.ConstU32(32u))}; + // value == 0 case is checked in IREmitter + return ctx.OpSelect(ctx.U32[1], found_hi, shifted_hi, lo_msb); +} + Id EmitFindILsb32(EmitContext& ctx, Id value) { return ctx.OpFindILsb(ctx.U32[1], value); } diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 3a8e894ae..7beb594c3 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -114,6 +114,8 @@ void Translator::EmitScalarAlu(const GcnInst& inst) { return S_FF1_I32_B64(inst); case Opcode::S_FLBIT_I32_B32: return S_FLBIT_I32_B32(inst); + case Opcode::S_FLBIT_I32_B64: + return S_FLBIT_I32_B64(inst); case Opcode::S_BITSET0_B32: return S_BITSET_B32(inst, 0); case Opcode::S_BITSET1_B32: @@ -686,6 +688,17 @@ void Translator::S_FLBIT_I32_B32(const GcnInst& inst) { SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); } +void Translator::S_FLBIT_I32_B64(const GcnInst& inst) { + const IR::U64 src0{GetSrc64(inst.src[0])}; + // Gcn wants the MSB position counting from the left, but SPIR-V counts from the rightmost (LSB) + // position + const IR::U32 msb_pos = ir.FindUMsb(src0); + const IR::U32 pos_from_left = ir.ISub(ir.Imm32(63), msb_pos); + // Select 0xFFFFFFFF if src0 was 0 + const IR::U1 cond = ir.INotEqual(src0, ir.Imm64(u64(0u))); + SetDst(inst.dst[0], IR::U32{ir.Select(cond, pos_from_left, ir.Imm32(~0U))}); +} + void Translator::S_BITSET_B32(const GcnInst& inst, u32 bit_value) { const IR::U32 old_value{GetSrc(inst.dst[0])}; const IR::U32 offset{ir.BitFieldExtract(GetSrc(inst.src[0]), ir.Imm32(0U), ir.Imm32(5U))}; diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 2584d5c5e..15ba8c8d7 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -121,6 +121,7 @@ public: void S_FF1_I32_B32(const GcnInst& inst); void S_FF1_I32_B64(const GcnInst& inst); void S_FLBIT_I32_B32(const GcnInst& inst); + void S_FLBIT_I32_B64(const GcnInst& inst); void S_BITSET_B32(const GcnInst& inst, u32 bit_value); void S_GETPC_B64(u32 pc, const GcnInst& inst); void S_SAVEEXEC_B64(NegateMode negate, bool is_or, const GcnInst& inst); diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index 01d945178..dcb734d01 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1546,8 +1546,15 @@ U32 IREmitter::FindSMsb(const U32& value) { return Inst(Opcode::FindSMsb32, value); } -U32 IREmitter::FindUMsb(const U32& value) { - return Inst(Opcode::FindUMsb32, value); +U32 IREmitter::FindUMsb(const U32U64& value) { + switch (value.Type()) { + case Type::U32: + return Inst(Opcode::FindUMsb32, value); + case Type::U64: + return Inst(Opcode::FindUMsb64, value); + default: + ThrowInvalidType(value.Type()); + } } U32 IREmitter::FindILsb(const U32U64& value) { diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 8f8a12736..da7adf42b 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -266,7 +266,7 @@ public: [[nodiscard]] U32 BitwiseNot(const U32& value); [[nodiscard]] U32 FindSMsb(const U32& value); - [[nodiscard]] U32 FindUMsb(const U32& value); + [[nodiscard]] U32 FindUMsb(const U32U64& value); [[nodiscard]] U32 FindILsb(const U32U64& value); [[nodiscard]] U32 SMin(const U32& a, const U32& b); [[nodiscard]] U32 UMin(const U32& a, const U32& b); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index ab6dbfde9..647432bcf 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -349,6 +349,7 @@ OPCODE(BitwiseNot32, U32, U32, OPCODE(FindSMsb32, U32, U32, ) OPCODE(FindUMsb32, U32, U32, ) +OPCODE(FindUMsb64, U32, U64, ) OPCODE(FindILsb32, U32, U32, ) OPCODE(FindILsb64, U32, U64, ) OPCODE(SMin32, U32, U32, U32, ) From 91d29459fb55cb0d28006639e7a38134c5a368ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?= Date: Fri, 6 Jun 2025 05:19:05 +0200 Subject: [PATCH 5/5] Implement PM4CondExec (#3046) --- src/video_core/amdgpu/liverpool.cpp | 13 +++++++++++++ src/video_core/amdgpu/pm4_cmds.h | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 118c43cef..e031d0ebc 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -765,6 +765,19 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); + if (cond_exec->command.Value() != 0) { + LOG_WARNING(Render, "IT_COND_EXEC used a reserved command"); + } + const auto skip = *cond_exec->Address() == false; + if (skip) { + dcb = NextPacket(dcb, + header->type3.NumWords() + 1 + cond_exec->exec_count.Value()); + continue; + } + break; + } default: UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}", static_cast(opcode), count); diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index 011e47bf0..23c1b8f21 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -1159,4 +1159,25 @@ struct PM4CmdMemSemaphore { } }; +struct PM4CmdCondExec { + PM4Type3Header header; + union { + BitField<2, 30, u32> bool_addr_lo; ///< low 32 address bits for the block in memory from + ///< where the CP will fetch the condition + }; + union { + BitField<0, 16, u32> bool_addr_hi; ///< high address bits for the condition + BitField<28, 4, u32> command; + }; + union { + BitField<0, 14, u32> exec_count; ///< Number of DWords that the CP will skip + ///< if bool pointed to is zero + }; + + bool* Address() const { + return std::bit_cast(u64(bool_addr_hi.Value()) << 32 | u64(bool_addr_lo.Value()) + << 2); + } +}; + } // namespace AmdGpu