From 4d1a1ce9c2aae933a3d4e9a0a07e55eb5e5875e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?=
Date: Thu, 5 Jun 2025 01:55:47 +0200
Subject: [PATCH 01/10] v_rcp_legacy_f32 (#3040)
---
.../frontend/translate/translate.h | 1 +
.../frontend/translate/vector_alu.cpp | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h
index 7b4b03f27..2584d5c5e 100644
--- a/src/shader_recompiler/frontend/translate/translate.h
+++ b/src/shader_recompiler/frontend/translate/translate.h
@@ -204,6 +204,7 @@ public:
void V_EXP_F32(const GcnInst& inst);
void V_LOG_F32(const GcnInst& inst);
void V_RCP_F32(const GcnInst& inst);
+ void V_RCP_LEGACY_F32(const GcnInst& inst);
void V_RCP_F64(const GcnInst& inst);
void V_RSQ_F32(const GcnInst& inst);
void V_SQRT_F32(const GcnInst& inst);
diff --git a/src/shader_recompiler/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp
index fb3f52c7f..3b88e4dec 100644
--- a/src/shader_recompiler/frontend/translate/vector_alu.cpp
+++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp
@@ -158,6 +158,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) {
return V_LOG_F32(inst);
case Opcode::V_RCP_F32:
return V_RCP_F32(inst);
+ case Opcode::V_RCP_LEGACY_F32:
+ return V_RCP_LEGACY_F32(inst);
case Opcode::V_RCP_F64:
return V_RCP_F64(inst);
case Opcode::V_RCP_IFLAG_F32:
@@ -798,6 +800,20 @@ void Translator::V_RCP_F32(const GcnInst& inst) {
SetDst(inst.dst[0], ir.FPRecip(src0));
}
+void Translator::V_RCP_LEGACY_F32(const GcnInst& inst) {
+ const IR::F32 src0{GetSrc(inst.src[0])};
+ const auto result = ir.FPRecip(src0);
+ const auto inf = ir.FPIsInf(result);
+
+ const auto raw_result = ir.ConvertFToU(32, result);
+ const auto sign_bit = ir.ShiftRightLogical(raw_result, ir.Imm32(31u));
+ const auto sign_bit_set = ir.INotEqual(sign_bit, ir.Imm32(0u));
+ const IR::F32 inf_result{ir.Select(sign_bit_set, ir.Imm32(-0.0f), ir.Imm32(0.0f))};
+ const IR::F32 val{ir.Select(inf, inf_result, result)};
+
+ SetDst(inst.dst[0], val);
+}
+
void Translator::V_RCP_F64(const GcnInst& inst) {
const IR::F64 src0{GetSrc64(inst.src[0])};
SetDst64(inst.dst[0], ir.FPRecip(src0));
From d4fbeea085d704a94151e44a5dcf686e2d33a7b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marcin=20Miko=C5=82ajczyk?=
Date: Thu, 5 Jun 2025 02:00:11 +0200
Subject: [PATCH 02/10] Stub PM4 COPY_DATA opcode (#3032)
---
src/video_core/amdgpu/liverpool.cpp | 15 ++++++--
src/video_core/amdgpu/pm4_cmds.h | 55 +++++++++++++++++++++++++++++
2 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp
index 4db7648c6..118c43cef 100644
--- a/src/video_core/amdgpu/liverpool.cpp
+++ b/src/video_core/amdgpu/liverpool.cpp
@@ -394,7 +394,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span dcb, std::span(header);
- LOG_DEBUG(Render_Vulkan,
- "Encountered EventWrite: event_type = {}, event_index = {}",
+ LOG_DEBUG(Render, "Encountered EventWrite: event_type = {}, event_index = {}",
magic_enum::enum_name(event->event_type.Value()),
magic_enum::enum_name(event->event_index.Value()));
if (event->event_type.Value() == EventType::SoVgtStreamoutFlush) {
@@ -673,6 +672,16 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header);
+ LOG_WARNING(Render,
+ "unhandled IT_COPY_DATA src_sel = {}, dst_sel = {}, "
+ "count_sel = {}, wr_confirm = {}, engine_sel = {}",
+ u32(copy_data->src_sel.Value()), u32(copy_data->dst_sel.Value()),
+ copy_data->count_sel.Value(), copy_data->wr_confirm.Value(),
+ u32(copy_data->engine_sel.Value()));
+ break;
+ }
case PM4ItOpcode::MemSemaphore: {
const auto* mem_semaphore = reinterpret_cast(header);
if (mem_semaphore->IsSignaling()) {
diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h
index 58ecda93e..011e47bf0 100644
--- a/src/video_core/amdgpu/pm4_cmds.h
+++ b/src/video_core/amdgpu/pm4_cmds.h
@@ -554,6 +554,61 @@ struct PM4DmaData {
}
};
+enum class CopyDataSrc : u32 {
+ MappedRegister = 0,
+ Memory = 1,
+ TCL2 = 2,
+ Gds = 3,
+ // Reserved = 4,
+ Immediate = 5,
+ Atomic = 6,
+ GdsAtomic0 = 7,
+ GdsAtomic1 = 8,
+ GpuClock = 9,
+};
+
+enum class CopyDataDst : u32 {
+ MappedRegister = 0,
+ MemorySync = 1,
+ TCL2 = 2,
+ Gds = 3,
+ // Reserved = 4,
+ MemoryAsync = 5,
+};
+
+enum class CopyDataEngine : u32 {
+ Me = 0,
+ Pfp = 1,
+ Ce = 2,
+ // Reserved = 3
+};
+
+struct PM4CmdCopyData {
+ PM4Type3Header header;
+ union {
+ BitField<0, 4, CopyDataSrc> src_sel;
+ BitField<8, 4, CopyDataDst> dst_sel;
+ BitField<16, 1, u32> count_sel;
+ BitField<20, 1, u32> wr_confirm;
+ BitField<30, 2, CopyDataEngine> engine_sel;
+ u32 control;
+ };
+ u32 src_addr_lo;
+ u32 src_addr_hi;
+ u32 dst_addr_lo;
+ u32 dst_addr_hi;
+
+ template
+ T SrcAddress() const {
+ return std::bit_cast(src_addr_lo | u64(src_addr_hi) << 32);
+ }
+
+ template
+ T DstAddress() const {
+ return std::bit_cast(dst_addr_lo | u64(dst_addr_hi) << 32);
+ }
+};
+
struct PM4CmdRewind {
PM4Type3Header header;
union {
From 285df1b5befcedb1287007ed992e1805b148025f Mon Sep 17 00:00:00 2001
From: DanielSvoboda
Date: Thu, 5 Jun 2025 02:48:47 -0300
Subject: [PATCH 03/10] QT: AutoUpdate - Fix Changelog Error (#3042)
---
.github/workflows/build.yml | 6 +++---
src/qt_gui/check_update.cpp | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ceb915f6a..bb3d157b7 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -494,7 +494,7 @@ jobs:
with:
token: ${{ secrets.SHADPS4_TOKEN_REPO }}
name: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}"
- tag: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}"
+ tag: "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}"
draft: false
prerelease: true
body: "Full Changelog: [${{ env.last_release_tag }}...${{ needs.get-info.outputs.shorthash }}](https://github.com/shadps4-emu/shadPS4/compare/${{ env.last_release_tag }}...${{ needs.get-info.outputs.fullhash }})"
@@ -530,14 +530,14 @@ jobs:
# Check if release already exists and get ID
release_id=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
- "https://api.github.com/repos/$REPO/releases/tags/Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}" | jq -r '.id')
+ "https://api.github.com/repos/$REPO/releases/tags/Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}" | jq -r '.id')
if [[ "$release_id" == "null" ]]; then
echo "Creating release in $REPO for $filename"
release_id=$(curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-d '{
- "tag_name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}",
+ "tag_name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.fullhash }}",
"name": "Pre-release-shadPS4-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }}",
"draft": false,
"prerelease": true,
diff --git a/src/qt_gui/check_update.cpp b/src/qt_gui/check_update.cpp
index 550fdddb5..b0858840a 100644
--- a/src/qt_gui/check_update.cpp
+++ b/src/qt_gui/check_update.cpp
@@ -137,7 +137,7 @@ tr("The Auto Updater allows up to 60 update checks per hour.\\nYou have reached
}
}
- latestRev = latestVersion.right(7);
+ latestRev = latestVersion.right(40);
latestDate = jsonObj["published_at"].toString();
QJsonArray assets = jsonObj["assets"].toArray();
@@ -167,7 +167,7 @@ tr("The Auto Updater allows up to 60 update checks per hour.\\nYou have reached
QDateTime dateTime = QDateTime::fromString(latestDate, Qt::ISODate);
latestDate = dateTime.isValid() ? dateTime.toString("yyyy-MM-dd HH:mm:ss") : "Unknown date";
- if (latestRev == currentRev.left(7)) {
+ if (latestRev == currentRev) {
if (showMessage) {
QMessageBox::information(this, tr("Auto Updater"),
tr("Your version is already up to date!"));
@@ -215,7 +215,7 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
"%3 | "
"(%4) | "
"
")
- .arg(currentRev.left(7), currentDate, latestRev, latestDate);
+ .arg(currentRev.left(7), currentDate, latestRev.left(7), latestDate);
QLabel* updateLabel = new QLabel(updateText, this);
layout->addWidget(updateLabel);
From 93222c6f9f01c15855b3cee23c7856b963b6b1e2 Mon Sep 17 00:00:00 2001
From: georgemoralis
Date: Thu, 5 Jun 2025 08:49:32 +0300
Subject: [PATCH 04/10] New Crowdin updates (#3038)
* New translations en_us.ts (Portuguese, Brazilian)
* New translations en_us.ts (Turkish)
---
src/qt_gui/translations/pt_BR.ts | 2 +-
src/qt_gui/translations/tr_TR.ts | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts
index 34d31f240..9f254e272 100644
--- a/src/qt_gui/translations/pt_BR.ts
+++ b/src/qt_gui/translations/pt_BR.ts
@@ -2048,7 +2048,7 @@
* Unsupported Vulkan Version
- * Unsupported Vulkan Version
+ * Versão do Vulkan não suportada
diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts
index e61985e90..c6d641470 100644
--- a/src/qt_gui/translations/tr_TR.ts
+++ b/src/qt_gui/translations/tr_TR.ts
@@ -138,7 +138,7 @@
File Exists
- Dosya mevcut
+ Dosya Mevcut
File already exists. Do you want to replace it?
@@ -1221,7 +1221,7 @@
Exit shadPS4
- shadPS4'ten Çık
+ shadPS4 Çıkış
Exit the application.
@@ -1381,7 +1381,7 @@
Game Boot
- Oyun Başlatma
+ Oyun Başlat
Only one file can be selected!
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 05/10] 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 06/10] [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 07/10] 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 08/10] 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 09/10] 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
From 5edd9ff54b6baca5025dff0f5491ddf0d0746a19 Mon Sep 17 00:00:00 2001
From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com>
Date: Sat, 7 Jun 2025 16:17:45 -0500
Subject: [PATCH 10/10] Improved sceKernelMapNamedFlexibleMemory logging
(#3050)
* More descriptive sceKernelMapNamedFlexibleMemory logging
* Misc exports
These functions are used by Overwatch: Origins Edition
* Clang
* Function parameter cleanup
Changes the parameters on our sceKernelMapNamedFlexibleMemory and sceKernelMapFlexibleMemory functions to better align with our current standards.
---
src/core/libraries/kernel/kernel.cpp | 4 ++++
src/core/libraries/kernel/memory.cpp | 21 +++++++++------------
src/core/libraries/kernel/memory.h | 7 +++----
src/core/libraries/kernel/threads/mutex.cpp | 1 +
4 files changed, 17 insertions(+), 16 deletions(-)
diff --git a/src/core/libraries/kernel/kernel.cpp b/src/core/libraries/kernel/kernel.cpp
index 180850217..930640d0e 100644
--- a/src/core/libraries/kernel/kernel.cpp
+++ b/src/core/libraries/kernel/kernel.cpp
@@ -273,6 +273,10 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
Libraries::Net::sceNetInetNtop); // TODO fix it to sys_ ...
LIB_FUNCTION("4n51s0zEf0c", "libScePosix", 1, "libkernel", 1, 1,
Libraries::Net::sceNetInetPton); // TODO fix it to sys_ ...
+ LIB_FUNCTION("XVL8So3QJUk", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_connect);
+ LIB_FUNCTION("3e+4Iv7IJ8U", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_accept);
+ LIB_FUNCTION("aNeavPDNKzA", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_sendmsg);
+ LIB_FUNCTION("pxnCmagrtao", "libScePosix", 1, "libkernel", 1, 1, Libraries::Net::sys_listen);
}
} // namespace Libraries::Kernel
diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp
index 18676cbdf..5e94199e1 100644
--- a/src/core/libraries/kernel/memory.cpp
+++ b/src/core/libraries/kernel/memory.cpp
@@ -222,9 +222,10 @@ s32 PS4_SYSV_ABI sceKernelMapDirectMemory2(void** addr, u64 len, s32 type, s32 p
return ret;
}
-s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
- int flags, const char* name) {
-
+s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags,
+ const char* name) {
+ LOG_INFO(Kernel_Vmm, "in_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}, name = '{}'",
+ fmt::ptr(*addr_in_out), len, prot, flags, name);
if (len == 0 || !Common::Is16KBAligned(len)) {
LOG_ERROR(Kernel_Vmm, "len is 0 or not 16kb multiple");
return ORBIS_KERNEL_ERROR_EINVAL;
@@ -243,18 +244,14 @@ s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, std::size_t
const VAddr in_addr = reinterpret_cast(*addr_in_out);
const auto mem_prot = static_cast(prot);
const auto map_flags = static_cast(flags);
- SCOPE_EXIT {
- LOG_INFO(Kernel_Vmm,
- "in_addr = {:#x}, out_addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}",
- in_addr, fmt::ptr(*addr_in_out), len, prot, flags);
- };
auto* memory = Core::Memory::Instance();
- return memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags,
- Core::VMAType::Flexible, name);
+ const auto ret = memory->MapMemory(addr_in_out, in_addr, len, mem_prot, map_flags,
+ Core::VMAType::Flexible, name);
+ LOG_INFO(Kernel_Vmm, "out_addr = {}", fmt::ptr(*addr_in_out));
+ return ret;
}
-s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
- int flags) {
+s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags) {
return sceKernelMapNamedFlexibleMemory(addr_in_out, len, prot, flags, "anon");
}
diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h
index 6cefe0d07..ea42e7546 100644
--- a/src/core/libraries/kernel/memory.h
+++ b/src/core/libraries/kernel/memory.h
@@ -141,10 +141,9 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE
s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtualQueryInfo* info,
size_t infoSize);
s32 PS4_SYSV_ABI sceKernelReserveVirtualRange(void** addr, u64 len, int flags, u64 alignment);
-s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addrInOut, std::size_t len, int prot,
- int flags, const char* name);
-s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, std::size_t len, int prot,
- int flags);
+s32 PS4_SYSV_ABI sceKernelMapNamedFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags,
+ const char* name);
+s32 PS4_SYSV_ABI sceKernelMapFlexibleMemory(void** addr_in_out, u64 len, s32 prot, s32 flags);
int PS4_SYSV_ABI sceKernelQueryMemoryProtection(void* addr, void** start, void** end, u32* prot);
s32 PS4_SYSV_ABI sceKernelMprotect(const void* addr, u64 size, s32 prot);
diff --git a/src/core/libraries/kernel/threads/mutex.cpp b/src/core/libraries/kernel/threads/mutex.cpp
index 956e5ef65..3dbade96a 100644
--- a/src/core/libraries/kernel/threads/mutex.cpp
+++ b/src/core/libraries/kernel/threads/mutex.cpp
@@ -426,6 +426,7 @@ void RegisterMutex(Core::Loader::SymbolsResolver* sym) {
// Posix
LIB_FUNCTION("ttHNfU+qDBU", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_init);
LIB_FUNCTION("7H0iTOciTLo", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_lock);
+ LIB_FUNCTION("Io9+nTKXZtA", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_timedlock);
LIB_FUNCTION("2Z+PpY6CaJg", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_unlock);
LIB_FUNCTION("ltCfaGr2JGE", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutex_destroy);
LIB_FUNCTION("dQHWEsJtoE4", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_mutexattr_init);