From 247e935353852bdb64bcfe76a5f74ab2c6c01239 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 15 Apr 2025 17:13:19 -0700 Subject: [PATCH 01/41] externals: Update MoltenVK (#2791) --- .gitmodules | 2 +- externals/MoltenVK/MoltenVK | 2 +- externals/MoltenVK/SPIRV-Cross | 2 +- src/video_core/renderer_vulkan/vk_instance.cpp | 5 +---- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.gitmodules b/.gitmodules index 065a4570f..9daefe305 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,7 +97,7 @@ shallow = true [submodule "externals/MoltenVK/SPIRV-Cross"] path = externals/MoltenVK/SPIRV-Cross - url = https://github.com/KhronosGroup/SPIRV-Cross + url = https://github.com/billhollings/SPIRV-Cross shallow = true [submodule "externals/MoltenVK/MoltenVK"] path = externals/MoltenVK/MoltenVK diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 83510e0f3..067fc6c85 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 83510e0f3835c3c43651dda087305abc42572e17 +Subproject commit 067fc6c85b02f37dfda58eeda49d8458e093ed60 diff --git a/externals/MoltenVK/SPIRV-Cross b/externals/MoltenVK/SPIRV-Cross index 68300dc07..185833a61 160000 --- a/externals/MoltenVK/SPIRV-Cross +++ b/externals/MoltenVK/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 68300dc07ac3dc592dbbdb87e02d5180f984ad12 +Subproject commit 185833a61cbe29ce3bfb5a499ffb3dfeaee3bbe7 diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index d45889054..f83f63036 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -249,7 +249,7 @@ bool Instance::CreateDevice() { add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME); - const bool maintenance4 = add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); + add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); @@ -422,9 +422,6 @@ bool Instance::CreateDevice() { #endif }; - if (!maintenance4) { - device_chain.unlink(); - } if (!custom_border_color) { device_chain.unlink(); } From 3bc876ca78a680d76a346d175febe0f8ac4003dd Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 15 Apr 2025 22:31:58 -0700 Subject: [PATCH 02/41] renderer_vulkan: Improve handling of required vs optional extensions. (#2792) * renderer_vulkan: Improve handling of required vs optional extensions. * documents: Update quickstart Vulkan requirements. --- documents/Quickstart/Quickstart.md | 4 +- .../renderer_vulkan/vk_instance.cpp | 25 +++++++------ src/video_core/renderer_vulkan/vk_instance.h | 6 +++ .../renderer_vulkan/vk_rasterizer.cpp | 37 +++++++++++-------- 4 files changed, 43 insertions(+), 29 deletions(-) diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md index 55825ac7d..62df95e71 100644 --- a/documents/Quickstart/Quickstart.md +++ b/documents/Quickstart/Quickstart.md @@ -29,8 +29,8 @@ SPDX-License-Identifier: GPL-2.0-or-later ### GPU - A graphics card with at least 1GB of VRAM -- Keep your graphics drivers up to date -- Vulkan 1.3 support (required) +- Up-to-date graphics drivers +- Vulkan 1.3 with the `VK_KHR_swapchain` and `VK_KHR_push_descriptor` extensions ### RAM diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index f83f63036..f20e91ec8 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -242,18 +242,21 @@ bool Instance::CreateDevice() { // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 // with extensions. - add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME); - add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME); - add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); - add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME); - add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); - add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); - add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME); - add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME); + ASSERT(add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)); + ASSERT(add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME)); + ASSERT(add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)); + ASSERT(add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME)); + ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)); + ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME)); + ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME)); + ASSERT(add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME)); - add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME); - add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME); - add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); + // Required + ASSERT(add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)); + ASSERT(add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)); + + // Optional + depth_range_unrestricted = add_extension(VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME); dynamic_state_3 = add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); if (dynamic_state_3) { dynamic_state_3_features = diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 6de419041..a9de01f84 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -104,6 +104,11 @@ public: return depth_clip_control; } + /// Returns true when VK_EXT_depth_range_unrestricted is supported + bool IsDepthRangeUnrestrictedSupported() const { + return depth_range_unrestricted; + } + /// Returns true when the extendedDynamicState3ColorWriteMask feature of /// VK_EXT_extended_dynamic_state3 is supported. bool IsDynamicColorWriteMaskSupported() const { @@ -340,6 +345,7 @@ private: bool custom_border_color{}; bool fragment_shader_barycentric{}; bool depth_clip_control{}; + bool depth_range_unrestricted{}; bool dynamic_state_3{}; bool vertex_input_dynamic_state{}; bool robustness2{}; diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 13779977d..f8d09f011 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1018,32 +1018,37 @@ void Rasterizer::UpdateViewportScissorState() const { const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f; const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f; + + vk::Viewport viewport = { + .minDepth = zoffset - zscale * reduce_z, + .maxDepth = zscale + zoffset, + }; + if (!instance.IsDepthRangeUnrestrictedSupported()) { + // Unrestricted depth range not supported by device. Make best attempt + // by restricting to valid range. + viewport.minDepth = std::max(viewport.minDepth, 0.f); + viewport.maxDepth = std::min(viewport.maxDepth, 1.f); + } if (regs.IsClipDisabled()) { // In case if clipping is disabled we patch the shader to convert vertex position // from screen space coordinates to NDC by defining a render space as full hardware // window range [0..16383, 0..16383] and setting the viewport to its size. - viewports.push_back({ - .x = 0.f, - .y = 0.f, - .width = float(std::min(instance.GetMaxViewportWidth(), 16_KB)), - .height = float(std::min(instance.GetMaxViewportHeight(), 16_KB)), - .minDepth = zoffset - zscale * reduce_z, - .maxDepth = zscale + zoffset, - }); + viewport.x = 0.f; + viewport.y = 0.f; + viewport.width = float(std::min(instance.GetMaxViewportWidth(), 16_KB)); + viewport.height = float(std::min(instance.GetMaxViewportHeight(), 16_KB)); } else { const auto xoffset = vp_ctl.xoffset_enable ? vp.xoffset : 0.f; const auto xscale = vp_ctl.xscale_enable ? vp.xscale : 1.f; const auto yoffset = vp_ctl.yoffset_enable ? vp.yoffset : 0.f; const auto yscale = vp_ctl.yscale_enable ? vp.yscale : 1.f; - viewports.push_back({ - .x = xoffset - xscale, - .y = yoffset - yscale, - .width = xscale * 2.0f, - .height = yscale * 2.0f, - .minDepth = zoffset - zscale * reduce_z, - .maxDepth = zscale + zoffset, - }); + + viewport.x = xoffset - xscale; + viewport.y = yoffset - yscale; + viewport.width = xscale * 2.0f; + viewport.height = yscale * 2.0f; } + viewports.push_back(viewport); auto vp_scsr = scsr; if (regs.mode_control.vport_scissor_enable) { From 52ab1ed04b900206c989a3cb78932217421d545a Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 16 Apr 2025 08:08:09 -0700 Subject: [PATCH 03/41] shader_recompiler: Implement S_FLBIT_I32_B32 and V_MUL_HI_I32. (#2793) --- .../backend/spirv/emit_spirv_instructions.h | 4 ++-- .../backend/spirv/emit_spirv_integer.cpp | 13 +++++++++---- .../frontend/translate/scalar_alu.cpp | 13 +++++++++++++ .../frontend/translate/translate.h | 1 + .../frontend/translate/vector_alu.cpp | 4 +++- src/shader_recompiler/ir/ir_emitter.cpp | 4 ++-- src/shader_recompiler/ir/ir_emitter.h | 2 +- src/shader_recompiler/ir/opcodes.inc | 4 ++-- 8 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index fb37799f5..68438fbba 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -338,8 +338,8 @@ Id EmitIAdd64(EmitContext& ctx, Id a, Id b); Id EmitIAddCary32(EmitContext& ctx, Id a, Id b); Id EmitISub32(EmitContext& ctx, Id a, Id b); Id EmitISub64(EmitContext& ctx, Id a, Id b); -Id EmitSMulExt(EmitContext& ctx, Id a, Id b); -Id EmitUMulExt(EmitContext& ctx, Id a, Id b); +Id EmitSMulHi(EmitContext& ctx, Id a, Id b); +Id EmitUMulHi(EmitContext& ctx, Id a, Id b); Id EmitIMul32(EmitContext& ctx, Id a, Id b); Id EmitIMul64(EmitContext& ctx, Id a, Id b); Id EmitSDiv32(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 36726b6df..10bfbb2ab 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_integer.cpp @@ -72,12 +72,17 @@ Id EmitISub64(EmitContext& ctx, Id a, Id b) { return ctx.OpISub(ctx.U64, a, b); } -Id EmitSMulExt(EmitContext& ctx, Id a, Id b) { - return ctx.OpSMulExtended(ctx.full_result_i32x2, a, b); +Id EmitSMulHi(EmitContext& ctx, Id a, Id b) { + const auto signed_a{ctx.OpBitcast(ctx.S32[1], a)}; + const auto signed_b{ctx.OpBitcast(ctx.S32[1], b)}; + const auto mul_ext{ctx.OpSMulExtended(ctx.full_result_i32x2, signed_a, signed_b)}; + const auto signed_hi{ctx.OpCompositeExtract(ctx.S32[1], mul_ext, 1)}; + return ctx.OpBitcast(ctx.U32[1], signed_hi); } -Id EmitUMulExt(EmitContext& ctx, Id a, Id b) { - return ctx.OpUMulExtended(ctx.full_result_u32x2, a, b); +Id EmitUMulHi(EmitContext& ctx, Id a, Id b) { + const auto mul_ext{ctx.OpUMulExtended(ctx.full_result_u32x2, a, b)}; + return ctx.OpCompositeExtract(ctx.U32[1], mul_ext, 1); } Id EmitIMul32(EmitContext& ctx, Id a, Id b) { diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index 39f972848..c21c9b611 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -110,6 +110,8 @@ void Translator::EmitScalarAlu(const GcnInst& inst) { return S_FF1_I32_B32(inst); case Opcode::S_FF1_I32_B64: return S_FF1_I32_B64(inst); + case Opcode::S_FLBIT_I32_B32: + return S_FLBIT_I32_B32(inst); case Opcode::S_BITSET0_B32: return S_BITSET_B32(inst, 0); case Opcode::S_BITSET1_B32: @@ -660,6 +662,17 @@ void Translator::S_FF1_I32_B64(const GcnInst& inst) { SetDst(inst.dst[0], result); } +void Translator::S_FLBIT_I32_B32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(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(31), msb_pos); + // Select 0xFFFFFFFF if src0 was 0 + const IR::U1 cond = ir.INotEqual(src0, ir.Imm32(0)); + 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 6803cda25..520720b0f 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -119,6 +119,7 @@ public: void S_BCNT1_I32_B64(const GcnInst& inst); 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_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/frontend/translate/vector_alu.cpp b/src/shader_recompiler/frontend/translate/vector_alu.cpp index da25f5434..787cf6ad3 100644 --- a/src/shader_recompiler/frontend/translate/vector_alu.cpp +++ b/src/shader_recompiler/frontend/translate/vector_alu.cpp @@ -394,6 +394,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) { return V_MUL_HI_U32(false, inst); case Opcode::V_MUL_LO_I32: return V_MUL_LO_U32(inst); + case Opcode::V_MUL_HI_I32: + return V_MUL_HI_U32(true, inst); case Opcode::V_MAD_U64_U32: return V_MAD_U64_U32(inst); case Opcode::V_NOP: @@ -1279,7 +1281,7 @@ void Translator::V_MUL_LO_U32(const GcnInst& inst) { void Translator::V_MUL_HI_U32(bool is_signed, const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; - const IR::U32 hi{ir.CompositeExtract(ir.IMulExt(src0, src1, is_signed), 1)}; + const IR::U32 hi{ir.IMulHi(src0, src1, is_signed)}; SetDst(inst.dst[0], hi); } diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index a171d32a2..a51d126c7 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1388,8 +1388,8 @@ U32U64 IREmitter::ISub(const U32U64& a, const U32U64& b) { } } -IR::Value IREmitter::IMulExt(const U32& a, const U32& b, bool is_signed) { - return Inst(is_signed ? Opcode::SMulExt : Opcode::UMulExt, a, b); +U32 IREmitter::IMulHi(const U32& a, const U32& b, bool is_signed) { + return Inst(is_signed ? Opcode::SMulHi : Opcode::UMulHi, a, b); } U32U64 IREmitter::IMul(const U32U64& a, const U32U64& b) { diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index 48cc02725..f1d564b80 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -240,7 +240,7 @@ public: [[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b); [[nodiscard]] Value IAddCary(const U32& a, const U32& b); [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b); - [[nodiscard]] Value IMulExt(const U32& a, const U32& b, bool is_signed = false); + [[nodiscard]] U32 IMulHi(const U32& a, const U32& b, bool is_signed = false); [[nodiscard]] U32U64 IMul(const U32U64& a, const U32U64& b); [[nodiscard]] U32 IDiv(const U32& a, const U32& b, bool is_signed = false); [[nodiscard]] U32 IMod(const U32& a, const U32& b, bool is_signed = false); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 93d759b74..10819f898 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -317,8 +317,8 @@ OPCODE(ISub32, U32, U32, OPCODE(ISub64, U64, U64, U64, ) OPCODE(IMul32, U32, U32, U32, ) OPCODE(IMul64, U64, U64, U64, ) -OPCODE(SMulExt, U32x2, U32, U32, ) -OPCODE(UMulExt, U32x2, U32, U32, ) +OPCODE(SMulHi, U32, U32, U32, ) +OPCODE(UMulHi, U32, U32, U32, ) OPCODE(SDiv32, U32, U32, U32, ) OPCODE(UDiv32, U32, U32, U32, ) OPCODE(SMod32, U32, U32, U32, ) From 04e4ce0775a6a9aa4aa33456a92b68860c1c129f Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 16 Apr 2025 09:52:18 -0700 Subject: [PATCH 04/41] fix: Bad Intel drivers. --- src/video_core/renderer_vulkan/vk_instance.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index f20e91ec8..c28e22985 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -248,7 +248,7 @@ bool Instance::CreateDevice() { ASSERT(add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME)); ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)); ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME)); + ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME) || driver_id == vk::DriverId::eIntelProprietaryWindows); ASSERT(add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME)); // Required From 243ee04b1c37b319a3bcf6d3bbeccaff3eb041a8 Mon Sep 17 00:00:00 2001 From: Missake212 Date: Wed, 16 Apr 2025 17:54:05 +0100 Subject: [PATCH 05/41] Implement DS_READ2ST64_B64 (#2795) --- src/shader_recompiler/frontend/translate/data_share.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index 22f5b8644..acffae14b 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -67,6 +67,8 @@ void Translator::EmitDataShare(const GcnInst& inst) { return DS_READ(64, false, false, false, inst); case Opcode::DS_READ2_B64: return DS_READ(64, false, true, false, inst); + case Opcode::DS_READ2ST64_B64: + return DS_READ(64, false, true, true, inst); default: LogMissingOpcode(inst); } From ddf3df7f564baf6de5e472b2a060e53acbb467ca Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 16 Apr 2025 10:48:17 -0700 Subject: [PATCH 06/41] fix: clang-format --- src/video_core/renderer_vulkan/vk_instance.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index c28e22985..0df020116 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -248,7 +248,8 @@ bool Instance::CreateDevice() { ASSERT(add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME)); ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)); ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME) || driver_id == vk::DriverId::eIntelProprietaryWindows); + ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME) || + driver_id == vk::DriverId::eIntelProprietaryWindows); ASSERT(add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME)); // Required From aa8dab5371777105a3112498faa821d79aa3cab4 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Wed, 16 Apr 2025 23:24:18 +0200 Subject: [PATCH 07/41] shader_recompiler: Implement S_SUBB_U32 instruction (#2796) * add S_SUBB_U32 instruction * add missing case * move case to match enum --- .../frontend/translate/scalar_alu.cpp | 13 +++++++++++++ .../frontend/translate/translate.h | 1 + 2 files changed, 14 insertions(+) diff --git a/src/shader_recompiler/frontend/translate/scalar_alu.cpp b/src/shader_recompiler/frontend/translate/scalar_alu.cpp index c21c9b611..3a8e894ae 100644 --- a/src/shader_recompiler/frontend/translate/scalar_alu.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_alu.cpp @@ -30,6 +30,8 @@ void Translator::EmitScalarAlu(const GcnInst& inst) { return S_SUB_I32(inst); case Opcode::S_ADDC_U32: return S_ADDC_U32(inst); + case Opcode::S_SUBB_U32: + return S_SUBB_U32(inst); case Opcode::S_MIN_I32: return S_MIN_U32(true, inst); case Opcode::S_MIN_U32: @@ -238,6 +240,17 @@ void Translator::S_SUB_U32(const GcnInst& inst) { ir.SetScc(ir.IGreaterThan(src1, src0, false)); } +void Translator::S_SUBB_U32(const GcnInst& inst) { + const IR::U32 src0{GetSrc(inst.src[0])}; + const IR::U32 src1{GetSrc(inst.src[1])}; + const IR::U32 borrow{ir.Select(ir.GetScc(), ir.Imm32(1U), ir.Imm32(0U))}; + const IR::U32 result{ir.ISub(ir.ISub(src0, src1), borrow)}; + SetDst(inst.dst[0], result); + + const IR::U32 sum_with_borrow{ir.IAdd(src1, borrow)}; + ir.SetScc(ir.ILessThan(src0, sum_with_borrow, false)); +} + void Translator::S_ADD_I32(const GcnInst& inst) { const IR::U32 src0{GetSrc(inst.src[0])}; const IR::U32 src1{GetSrc(inst.src[1])}; diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 520720b0f..32185a21f 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -80,6 +80,7 @@ public: // SOP2 void S_ADD_U32(const GcnInst& inst); void S_SUB_U32(const GcnInst& inst); + void S_SUBB_U32(const GcnInst& inst); void S_ADD_I32(const GcnInst& inst); void S_SUB_I32(const GcnInst& inst); void S_ADDC_U32(const GcnInst& inst); From 62a4182aca6a33b1899e871c8ff35410708d3752 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 16 Apr 2025 17:35:14 -0700 Subject: [PATCH 08/41] shader_recompiler: Fill in IMAGE_GATHER4_* variants in table. (#2798) --- src/shader_recompiler/frontend/format.cpp | 64 +++++++++++------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/shader_recompiler/frontend/format.cpp b/src/shader_recompiler/frontend/format.cpp index f89f0a582..52c8c733e 100644 --- a/src/shader_recompiler/frontend/format.cpp +++ b/src/shader_recompiler/frontend/format.cpp @@ -3569,19 +3569,19 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, // 65 = IMAGE_GATHER4_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, {}, {}, // 68 = IMAGE_GATHER4_L - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 69 = IMAGE_GATHER4_B - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 70 = IMAGE_GATHER4_B_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 71 = IMAGE_GATHER4_LZ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, @@ -3589,19 +3589,19 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, // 73 = IMAGE_GATHER4_C_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, {}, {}, // 76 = IMAGE_GATHER4_C_L - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 77 = IMAGE_GATHER4_C_B - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 78 = IMAGE_GATHER4_C_B_CL - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 79 = IMAGE_GATHER4_C_LZ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, @@ -3609,19 +3609,19 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, // 81 = IMAGE_GATHER4_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, {}, {}, // 84 = IMAGE_GATHER4_L_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 85 = IMAGE_GATHER4_B_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 86 = IMAGE_GATHER4_B_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 87 = IMAGE_GATHER4_LZ_O {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, @@ -3629,19 +3629,19 @@ constexpr std::array InstructionFormatMIMG = {{ {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, // 89 = IMAGE_GATHER4_C_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, {}, {}, // 92 = IMAGE_GATHER4_C_L_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 93 = IMAGE_GATHER4_C_B_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 94 = IMAGE_GATHER4_C_B_CL_O - {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, - ScalarType::Undefined}, + {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, + ScalarType::Float32}, // 95 = IMAGE_GATHER4_C_LZ_O {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32, ScalarType::Float32}, From ddc05e8a5f43819ce76340552cfcd2b9db6641ff Mon Sep 17 00:00:00 2001 From: Dmugetsu <168934208+diegolix29@users.noreply.github.com> Date: Wed, 16 Apr 2025 18:56:27 -0600 Subject: [PATCH 09/41] Implementing DS_SUB_U32, DS_INC_U32, DS_DEC_U32. (#2797) * Implementing DS_SUB_U32, DS_INC_U32, DS_DEC_U32, DS_WRITE_SRC2_B32, DS_WRITE_SRC2_B64. * Added ir instructions for new opcodes. Removing Write implementations. Maping operation S_BFE_I32 as it was added in translate but wasnt pointing to anything. * Suggestions --- .../backend/spirv/emit_spirv_atomic.cpp | 21 ++++++++++ .../backend/spirv/emit_spirv_instructions.h | 4 ++ .../frontend/translate/data_share.cpp | 42 +++++++++++++++++++ .../frontend/translate/translate.h | 3 ++ src/shader_recompiler/ir/ir_emitter.cpp | 12 ++++++ src/shader_recompiler/ir/ir_emitter.h | 4 ++ src/shader_recompiler/ir/opcodes.inc | 3 ++ 7 files changed, 89 insertions(+) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index 4faa99fe8..c6ec65606 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -21,6 +21,15 @@ Id SharedAtomicU32(EmitContext& ctx, Id offset, Id value, return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value); } +Id SharedAtomicU32_IncDec(EmitContext& ctx, Id offset, + Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id)) { + const Id shift_id{ctx.ConstU32(2U)}; + const Id index{ctx.OpShiftRightArithmetic(ctx.U32[1], offset, shift_id)}; + const Id pointer{ctx.OpAccessChain(ctx.shared_u32, ctx.shared_memory_u32, index)}; + const auto [scope, semantics]{AtomicArgs(ctx)}; + return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics); +} + Id BufferAtomicU32BoundsCheck(EmitContext& ctx, Id index, Id buffer_size, auto emit_func) { if (Sirit::ValidId(buffer_size)) { // Bounds checking enabled, wrap in a conditional branch to make sure that @@ -99,6 +108,18 @@ Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value) { return SharedAtomicU32(ctx, offset, value, &Sirit::Module::OpAtomicXor); } +Id EmitSharedAtomicISub32(EmitContext& ctx, Id offset, Id value) { + return SharedAtomicU32(ctx, offset, value, &Sirit::Module::OpAtomicISub); +} + +Id EmitSharedAtomicIIncrement32(EmitContext& ctx, Id offset) { + return SharedAtomicU32_IncDec(ctx, offset, &Sirit::Module::OpAtomicIIncrement); +} + +Id EmitSharedAtomicIDecrement32(EmitContext& ctx, Id offset) { + return SharedAtomicU32_IncDec(ctx, offset, &Sirit::Module::OpAtomicIDecrement); +} + Id EmitBufferAtomicIAdd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value) { return BufferAtomicU32(ctx, inst, handle, address, value, &Sirit::Module::OpAtomicIAdd); } diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index 68438fbba..9b7528be8 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -130,6 +130,10 @@ Id EmitSharedAtomicSMin32(EmitContext& ctx, Id offset, Id value); Id EmitSharedAtomicAnd32(EmitContext& ctx, Id offset, Id value); Id EmitSharedAtomicOr32(EmitContext& ctx, Id offset, Id value); Id EmitSharedAtomicXor32(EmitContext& ctx, Id offset, Id value); +Id EmitSharedAtomicIIncrement32(EmitContext& ctx, Id offset); +Id EmitSharedAtomicIDecrement32(EmitContext& ctx, Id offset); +Id EmitSharedAtomicISub32(EmitContext& ctx, Id offset, Id value); + Id EmitCompositeConstructU32x2(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2); Id EmitCompositeConstructU32x3(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3); Id EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst* inst, Id e1, Id e2, Id e3, Id e4); diff --git a/src/shader_recompiler/frontend/translate/data_share.cpp b/src/shader_recompiler/frontend/translate/data_share.cpp index acffae14b..c29497ada 100644 --- a/src/shader_recompiler/frontend/translate/data_share.cpp +++ b/src/shader_recompiler/frontend/translate/data_share.cpp @@ -13,6 +13,12 @@ void Translator::EmitDataShare(const GcnInst& inst) { // DS case Opcode::DS_ADD_U32: return DS_ADD_U32(inst, false); + case Opcode::DS_SUB_U32: + return DS_SUB_U32(inst, false); + case Opcode::DS_INC_U32: + return DS_INC_U32(inst, false); + case Opcode::DS_DEC_U32: + return DS_DEC_U32(inst, false); case Opcode::DS_MIN_I32: return DS_MIN_U32(inst, true, false); case Opcode::DS_MAX_I32: @@ -35,6 +41,8 @@ void Translator::EmitDataShare(const GcnInst& inst) { return DS_WRITE(32, false, true, true, inst); case Opcode::DS_ADD_RTN_U32: return DS_ADD_U32(inst, true); + case Opcode::DS_SUB_RTN_U32: + return DS_SUB_U32(inst, true); case Opcode::DS_MIN_RTN_U32: return DS_MIN_U32(inst, false, true); case Opcode::DS_MAX_RTN_U32: @@ -228,6 +236,40 @@ void Translator::DS_SWIZZLE_B32(const GcnInst& inst) { SetDst(inst.dst[0], ir.QuadShuffle(src, index)); } +void Translator::DS_INC_U32(const GcnInst& inst, bool rtn) { + const IR::U32 addr{GetSrc(inst.src[0])}; + const IR::U32 offset = + ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0)); + const IR::U32 addr_offset = ir.IAdd(addr, offset); + const IR::Value original_val = ir.SharedAtomicIIncrement(addr_offset); + if (rtn) { + SetDst(inst.dst[0], IR::U32{original_val}); + } +} + +void Translator::DS_DEC_U32(const GcnInst& inst, bool rtn) { + const IR::U32 addr{GetSrc(inst.src[0])}; + const IR::U32 offset = + ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0)); + const IR::U32 addr_offset = ir.IAdd(addr, offset); + const IR::Value original_val = ir.SharedAtomicIDecrement(addr_offset); + if (rtn) { + SetDst(inst.dst[0], IR::U32{original_val}); + } +} + +void Translator::DS_SUB_U32(const GcnInst& inst, bool rtn) { + const IR::U32 addr{GetSrc(inst.src[0])}; + const IR::U32 data{GetSrc(inst.src[1])}; + const IR::U32 offset = + ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0)); + const IR::U32 addr_offset = ir.IAdd(addr, offset); + const IR::Value original_val = ir.SharedAtomicISub(addr_offset, data); + if (rtn) { + SetDst(inst.dst[0], IR::U32{original_val}); + } +} + void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst) { const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))}; diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index 32185a21f..68d5e8dc8 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -275,6 +275,9 @@ public: void DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64, const GcnInst& inst); void DS_APPEND(const GcnInst& inst); void DS_CONSUME(const GcnInst& inst); + void DS_SUB_U32(const GcnInst& inst, bool rtn); + void DS_INC_U32(const GcnInst& inst, bool rtn); + void DS_DEC_U32(const GcnInst& inst, bool rtn); // Buffer Memory // MUBUF / MTBUF diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index a51d126c7..e8836bb4c 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -357,6 +357,18 @@ U32 IREmitter::SharedAtomicXor(const U32& address, const U32& data) { return Inst(Opcode::SharedAtomicXor32, address, data); } +U32 IREmitter::SharedAtomicIIncrement(const U32& address) { + return Inst(Opcode::SharedAtomicIIncrement32, address); +} + +U32 IREmitter::SharedAtomicIDecrement(const U32& address) { + return Inst(Opcode::SharedAtomicIDecrement32, address); +} + +U32 IREmitter::SharedAtomicISub(const U32& address, const U32& data) { + return Inst(Opcode::SharedAtomicISub32, address, data); +} + U32 IREmitter::ReadConst(const Value& base, const U32& offset) { return Inst(Opcode::ReadConst, base, offset); } diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index f1d564b80..186d83a07 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -106,6 +106,10 @@ public: [[nodiscard]] U32 SharedAtomicOr(const U32& address, const U32& data); [[nodiscard]] U32 SharedAtomicXor(const U32& address, const U32& data); + [[nodiscard]] U32 SharedAtomicIIncrement(const U32& address); + [[nodiscard]] U32 SharedAtomicIDecrement(const U32& address); + [[nodiscard]] U32 SharedAtomicISub(const U32& address, const U32& data); + [[nodiscard]] U32 ReadConst(const Value& base, const U32& offset); [[nodiscard]] U32 ReadConstBuffer(const Value& handle, const U32& index); diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 10819f898..4932ff9a0 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -44,6 +44,9 @@ OPCODE(SharedAtomicUMax32, U32, U32, OPCODE(SharedAtomicAnd32, U32, U32, U32, ) OPCODE(SharedAtomicOr32, U32, U32, U32, ) OPCODE(SharedAtomicXor32, U32, U32, U32, ) +OPCODE(SharedAtomicISub32, U32, U32, U32, ) +OPCODE(SharedAtomicIIncrement32, U32, U32, ) +OPCODE(SharedAtomicIDecrement32, U32, U32, ) // Context getters/setters OPCODE(GetUserData, U32, ScalarReg, ) From b1b7538afdf02b3bacf8c13b42cfb19d09bf5380 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Thu, 17 Apr 2025 09:42:26 +0300 Subject: [PATCH 10/41] New Crowdin updates (#2785) * New translations en_us.ts (Arabic) * New translations en_us.ts (Italian) * New translations en_us.ts (Arabic) * New translations en_us.ts (Arabic) * New translations en_us.ts (Arabic) --- src/qt_gui/translations/ar_SA.ts | 299 ++++++++++++++++--------------- src/qt_gui/translations/it_IT.ts | 2 +- 2 files changed, 151 insertions(+), 150 deletions(-) diff --git a/src/qt_gui/translations/ar_SA.ts b/src/qt_gui/translations/ar_SA.ts index f71ec7d3a..7ef3c6171 100644 --- a/src/qt_gui/translations/ar_SA.ts +++ b/src/qt_gui/translations/ar_SA.ts @@ -7,34 +7,34 @@ AboutDialog About shadPS4 - حول shadPS4 + حول محاكي الظل PS4 shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 هو محاكي تجريبي مفتوح المصدر لجهاز PlayStation 4. + محاكي الظل هو محاكي تجريبي مفتوح المصدر مخصص لـ PS4 This software should not be used to play games you have not legally obtained. - يجب عدم استخدام هذا البرنامج لتشغيل الألعاب التي لم تحصل عليها بشكل قانوني. + لا تستخدم هذا البرنامج لتشغيل الألعاب بطريقة غير قانونية. CheatsPatches Cheats / Patches for - الغِشّ / التصحيحات + شفرات / إصلاحات لـ Cheats/Patches are experimental.\nUse with caution.\n\nDownload cheats individually by selecting the repository and clicking the download button.\nIn the Patches tab, you can download all patches at once, choose which ones you want to use, and save your selection.\n\nSince we do not develop the Cheats/Patches,\nplease report issues to the cheat author.\n\nCreated a new cheat? Visit:\n - الغش والتصحيحات هي ميزات تجريبية.\nاستخدمها بحذر.\n\nقم بتنزيل الغش بشكل فردي عن طريق اختيار المستودع والنقر على زر التنزيل.\nفي علامة تبويب التصحيحات، يمكنك تنزيل جميع التصحيحات دفعة واحدة، واختيار ما تريد استخدامه، وحفظ اختياراتك.\n\nنظرًا لأننا لا نقوم بتطوير الغش/التصحيحات،\nيرجى الإبلاغ عن أي مشاكل إلى مؤلف الغش.\n\nهل قمت بإنشاء غش جديد؟ قم بزيارة:\n + الشفرات والإصلاحات هي ميزات تجريبية.\nاستخدمها بحذر.\n\nقم بتنزيل الشفرات بشكل فردي عن طريق اختيار المستودع والضغط على تنزيل.\nفي علامة تبويب الإصلاحات، يمكنك تنزيل جميع الإصلاحات دفعة واحدة، واختيار ما تريد استخدامه، وحفظ اختياراتك.\n\nنظرًا لأننا لا نقوم بتطوير الشفرات والإصلاحات ،\nيرجى الإبلاغ عن أي مشاكل إلى مؤلف الشفرات.\n\nهل قمت بإنشاء شفرة جديد؟ قم بزيارة:\n No Image Available - لا تتوفر صورة + الصورة غير موجودة Serial: - الرقم التسلسلي: + الرَّقَم التسلسلي: Version: @@ -46,7 +46,7 @@ Select Cheat File: - اختر ملف الغش: + حدد مِلَفّ الشفرات: Repository: @@ -54,7 +54,7 @@ Download Cheats - تنزيل الغش + تحميل الشفرات Delete File @@ -66,19 +66,19 @@ You can delete the cheats you don't want after downloading them. - يمكنك حذف الغش الذي لا تريده بعد تنزيله. + يمكنك حذف الشفرات التي لا تريدها بعد تنزيلها. Do you want to delete the selected file?\n%1 - هل تريد حذف الملف المحدد؟\n%1 + هل ترغب في حذف الملف المحدد؟\n%1 Select Patch File: - اختر ملف التصحيح: + إختر ملف الباتش: Download Patches - تنزيل التصحيحات + تحميل الباتشات Save @@ -86,7 +86,7 @@ Cheats - الغش + الشفرات Patches @@ -106,7 +106,7 @@ No patch file found for the current serial. - لم يتم العثور على ملف تصحيح للرقم التسلسلي الحالي. + لم يتم العثور على مِلَفّ باتش للسيريال الحالي. Unable to open the file for reading. @@ -142,7 +142,7 @@ File already exists. Do you want to replace it? - الملف موجود بالفعل. هل تريد استبداله؟ + يوجد ملف بنفس الاسم. هل ترغب في استبداله؟ Failed to save file: @@ -154,19 +154,19 @@ Cheats Not Found - لم يتم العثور على الغش + لم يتم العثور على أي شفرات No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. - لم يتم العثور على غش لهذه اللعبة في هذا الإصدار من المستودع المحدد. حاول استخدام مستودع آخر أو إصدار آخر من اللعبة. + لم يتم العثور على شفرات لهذه اللعبة في هذه النسخة من المستودع المحدد. حاول استخدام مستودع آخر أو نسخة مختلفة من اللعبة. Cheats Downloaded Successfully - تم تنزيل الغش بنجاح + تم تحميل الشفرات بنجاح You have successfully downloaded the cheats for this version of the game from the selected repository. You can try downloading from another repository, if it is available it will also be possible to use it by selecting the file from the list. - لقد نجحت في تنزيل الغش لهذا الإصدار من اللعبة من المستودع المحدد. يمكنك محاولة التنزيل من مستودع آخر. إذا كان متاحًا، يمكنك اختياره عن طريق تحديد الملف من القائمة. + تم تحميل الشفرات بنجاح لهذه النسخة من اللعبة من المستودع الذي اخترته. إذا أردت، يمكنك تجربة مستودع آخر، وإذا كان متاحًا، يمكنك استخدام الشفرات عن طريق اختيار الملف من القائمة. Failed to save: @@ -194,7 +194,7 @@ The game is in version: %1 - اللعبة في الإصدار: %1 + النسخة الحالية للعبة هي: %1 The downloaded patch only works on version: %1 @@ -329,7 +329,7 @@ Network error occurred while trying to access the URL - حدث خطأ في الشبكة أثناء محاولة الوصول إلى عنوان URL + حدث خطأ في الشبكة عند محاولة الوصول إلى الموقع Download Complete @@ -388,11 +388,11 @@ Boots - أحذية + إقلاع Menus - قوائم + القائمة Ingame @@ -407,7 +407,7 @@ ControlSettings Configure Controls - تعديل عناصر التحكم + إعدادات التحكم D-Pad @@ -431,11 +431,11 @@ Left Stick Deadzone (def:2 max:127) - مدى تسجيل الإدخال للعصا اليسرى (التلقائي:2 حد أقصى:127) + النقطة العمياء للعصا اليسرى (الافتراضي: 2، الحد الأقصى: 127) Left Deadzone - إعدادات مدى تسجيل الإدخال لعصا التحكم اليسرى + النقطة العمياء لليسار Left Stick @@ -507,11 +507,11 @@ Right Stick Deadzone (def:2, max:127) - مدى تسجيل الإدخال للعصا اليمنى (التلقائي:2 حد أقصى:127) + النقطة العمياء للعصا اليمنى (الافتراضي: 2، الحد الأقصى: 127) Right Deadzone - إعدادات مدى تسجيل الإدخال لعصا التحكم اليمنى + النقطة العمياء اليمنى Right Stick @@ -617,7 +617,7 @@ ElfViewer Open Folder - فتح المجلد + افتح مجلد @@ -647,7 +647,7 @@ Browse - تصفح + استعراض Error @@ -718,15 +718,15 @@ Compatibility is untested - التوافق غير مختبر + لم يتم اختبار التوافق Game does not initialize properly / crashes the emulator - اللعبة لا تهيئ بشكل صحيح / تعطل المحاكي + اللعبة لا تبدأ بشكل صحيح / تتسبب في انهيار المحاكي Game boots, but only displays a blank screen - اللعبة تبدأ بالعمل، ولكن فقط تعرض شاشة فارغة + اللعبة تبدأ بالإقلاع، لكنها تعرض شاشة فارغة فقط Game displays an image but does not go past the menu @@ -734,15 +734,15 @@ Game has game-breaking glitches or unplayable performance - اللعبة بها قلتشات أو أداء غير قابل للتشغيل + اللعبة بها أخطاء جسيمة أو أداء يجعلها غير قابلة للعب Game can be completed with playable performance and no major glitches - يمكن الانتهاء من اللعبة مع الأداء القابل للتشغيل و لا توجد قلتشات كبيرة + يمكن إنهاء اللعبة بأداء جيد وبدون أعطال رئيسية Click to see details on github - انقر لرؤية التفاصيل على GitHub + اضغط لعرض التفاصيل على GitHub Last updated @@ -780,15 +780,15 @@ Cheats / Patches - الغش / التصحيحات + الشفرات / التصحيحات SFO Viewer - عارض SFO + عارض معلومات اللعبة (SFO) Trophy Viewer - عارض الجوائز + عارض الكؤوس Open Folder... @@ -820,11 +820,11 @@ Copy Version - إصدار النسخة + نسخ الإصدار Copy Size - حجم النسخة + نسخ حجم Copy All @@ -864,7 +864,7 @@ Submit a report - إرسال بلاغ + إرسال تقرير Shortcut creation @@ -888,7 +888,7 @@ This game has no update to delete! - لا تحتوي اللعبة على تحديث لحذفه! + لا يوجد تحديث لهذه اللعبة لحذفه! Update @@ -896,7 +896,7 @@ This game has no DLC to delete! - لا تحتوي اللعبة على DLC لحذفه! + لا توجد محتويات إضافية (DLC) لهذه اللعبة لحذفها! DLC @@ -916,11 +916,11 @@ Delete Save Data - حذف التخزينه + حذف بيانات الحفظ This game has no update folder to open! - لا تحتوي اللعبة على تحديث لفتحه! + لا يوجد مجلد تحديث لهذه اللعبة لفتحه! No log file found for this game! @@ -932,15 +932,15 @@ This game has no save data to delete! - هذه اللعبة لا تحتوي على أي تخزينات لحذفها! + لا توجد بيانات حفظ لهذه اللعبة لحذفها! This game has no saved trophies to delete! - هذه اللعبة ليس لديها كؤوس محفوظة للحذف! + لا توجد كؤوس محفوظة لهذه اللعبة لحذفها! Save Data - حفظ البيانات + بيانات الحفظ Trophy @@ -955,7 +955,7 @@ HelpDialog Quickstart - التشغيل السريع + البدء السريع FAQ @@ -963,22 +963,22 @@ Syntax - الصّيغة + البنية Special Bindings - إدخالات خاصة + الارتباطات الخاصة Keybindings - أزرار التحكم + تعيين الأزرار KBMSettings Configure Controls - تعديل عناصر التحكم + إعدادات جهاز التحكم D-Pad @@ -1026,7 +1026,7 @@ Use per-game configs - استخدام إعدادات كل لُعْبَة + استخدام إعدادات خاصة لكل لعبه L1 @@ -1038,7 +1038,7 @@ Text Editor - محرر النص + محرّر النصوص Help @@ -1058,15 +1058,15 @@ Touchpad Click - النقر على لوحة اللمس + زر لوحة اللمس Mouse to Joystick - الفأرة إلى عصا التحكم + تحويل الماوس إلى عصا التحكم *press F7 ingame to activate - * اضغط على F7 للتفعيل + * اضغط F7 داخل اللعبة للتفعيل R3 @@ -1078,15 +1078,15 @@ Mouse Movement Parameters - معطيات حركة الفأرة + إعدادات حركة الماوس note: click Help Button/Special Keybindings for more information - ملاحظة: انقر فوق زر المساعدة/روابط المفاتيح الخاصة للحصول على مزيد من المعلومات + ملاحظة: لمزيد من المعلومات عن التعيينات الخاصة، اضغط على زر المساعدة Face Buttons - أزرار الوجه + الأزرار الأمامية Triangle @@ -1106,11 +1106,11 @@ Right Analog Halfmode - تقليل سرعة عصا التحكم اليمنى للنصف + وضع النصف للعصا اليمنى (نصف الحساسية أو نصف الحركة) hold to move right stick at half-speed - الضغط باستمرار لتحريك العصا اليمنى بنصف السرعة + اضغط مع الاستمرار لتحريك العصا اليمنى بسرعة منخفضة Right Stick @@ -1118,15 +1118,15 @@ Speed Offset (def 0.125): - إزاحة السرعة (تلقائي 0.125): + تعويض السرعة (الافتراضي 0.125): Copy from Common Config - نسخ من الإعدادات الشائعة + نسخ من الإعدادات العامة Deadzone Offset (def 0.50): - إزاحة المدى الغير فعال (الأصل ٠.٥٠). + تعويض منطقة الخمول (الافتراضي 0.50): Speed Multiplier (def 1.0): @@ -1134,39 +1134,39 @@ Common Config Selected - الإعدادات الشائعة محدده + تم اختيار الإعدادات العامة This button copies mappings from the Common Config to the currently selected profile, and cannot be used when the currently selected profile is the Common Config. - هذا الزر يقوم بنسخ تعيينات الأزرار من إعدادات المستخدم العامة لإعدادات المستخدم المحددة حالياً، ولا يمكن استعماله عندما تكون الإعدادات المستخدمة هي الإعدادات العامة. + يقوم هذا الزر بنسخ التعيينات من الإعدادات العامة إلى الملف الشخصي المحدد حاليًا، ولا يمكن استخدامه إذا كانت الإعدادات العامة هي الملف المحدد. Copy values from Common Config - نسخ من الإعدادات الشائعة + نسخ القيم من الإعدادات العامة Do you want to overwrite existing mappings with the mappings from the Common Config? - هل تريد استبدال التعيينات الحالية بالتعيينات العامة؟ + هل تريد استبدال التعيينات الحالية بالتعيينات من الإعدادات العامة؟ Unable to Save - غير قادر على الحفظ + تعذّر الحفظ Cannot bind any unique input more than once - لا يمكن ربط أي إدخال فريد أكثر من مرة + لا يمكن تعيين نفس الزر لأكثر من وظيفة Press a key - اضغط على مفتاح + اضغط زرًا Cannot set mapping - لا يمكن تعيين الأزرار + تعذّر تعيين الزر Mousewheel cannot be mapped to stick outputs - عجلة الفأرة لا يمكن تعيينها لعصا التحكم + لا يمكن تعيين عجلة الفأرة لمخرجات العصا Save @@ -1189,7 +1189,7 @@ MainWindow Open/Add Elf Folder - Elf فتح/إضافة مجلد + فتح / إضافة مجلد Elf Boot Game @@ -1225,11 +1225,11 @@ Exit the application. - الخروج من التطبيق. + إغلاق التطبيق Show Game List - إظهار قائمة الألعاب + عرض قائمة الألعاب Game List Refresh @@ -1281,7 +1281,7 @@ No games found. Please add your games to your library first. - لم يتم العثور على ألعاب. الرجاء إضافة ألعابك إلى مكتبتك أولاً. + لم يتم العثور على ألعاب. يرجى إضافة ألعابك إلى المكتبة أولاً. Search... @@ -1345,7 +1345,7 @@ Game List - ققائمة الألعاب + قائمة الألعاب * Unsupported Vulkan Version @@ -1353,7 +1353,7 @@ Download Cheats For All Installed Games - تنزيل الغش لجميع الألعاب المثبتة + تحميل الشفرات لجميع الألعاب المثبتة Download Patches For All Games @@ -1365,7 +1365,7 @@ You have downloaded cheats for all the games you have installed. - لقد قمت بتنزيل الغش لجميع الألعاب التي قمت بتثبيتها. + تم تحميل الشفرات لجميع الألعاب المثبتة. Patches Downloaded Successfully! @@ -1409,11 +1409,11 @@ Play - أبدأ اللعب + تشغيل Pause - توقف مؤقت + إيقاف مؤقت Stop @@ -1425,11 +1425,11 @@ Full Screen - وضع ملء الشاشة + الشاشة الكاملة Controllers - أذرعة التحكم + وحدات التحكم Keyboard @@ -1445,7 +1445,7 @@ Show Labels Under Icons - إظهار العلامات أسفل الأيقونات + إظهار التسميات تحت الأيقونات @@ -1464,7 +1464,7 @@ Console Language - لغة وحدة التحكم + لغة النظام Emulator Language @@ -1476,11 +1476,11 @@ Default tab when opening settings - علامة التبويب الافتراضية عند فتح الإعدادات + التبويب الافتراضي عند فتح الإعدادات Show Game Size In List - عرض حجم اللعبة في القائمة + إظهار حجم اللعبة في القائمة Show Splash @@ -1496,7 +1496,7 @@ Trophy Key - زر الميداليات + مفتاح الكأس Trophy @@ -1504,11 +1504,11 @@ Open the custom trophy images/sounds folder - افتح مجلد تخصيص اصوات/صور الميداليات + فتح مجلد الصور/الأصوات المخصصة للكؤوس Logger - المسجل + سجل الأحداث Log Type @@ -1520,23 +1520,23 @@ Open Log Location - افتح موقع السجل + فتح موقع السجل Input - إدخال + إعدادات المدخلات Cursor - مؤشر + مؤشر الماوس Hide Cursor - إخفاء المؤشر + إخفاء مؤشر الماوس Hide Cursor Idle Timeout - مهلة إخفاء المؤشر عند الخمول + إخفاء المؤشر بعد فترة الخمول s @@ -1552,7 +1552,7 @@ Graphics - الرسومات + الرسوميات GUI @@ -1564,7 +1564,7 @@ Graphics Device - جهاز الرسومات + جهاز الرسوميات Vblank Divider @@ -1572,15 +1572,15 @@ Advanced - متقدم + الإعدادات المتقدمة Enable Shaders Dumping - تمكين تفريغ الشيدرات + تمكين تصدير الشيدرات Enable NULL GPU - تمكين وحدة معالجة الرسومات الفارغة + تمكين GPU فارغ Enable HDR @@ -1604,23 +1604,23 @@ Debug - تصحيح الأخطاء + التصحيح Enable Debug Dumping - تمكين تفريغ التصحيح + تمكين تصدير بيانات التصحيح Enable Vulkan Validation Layers - Vulkan تمكين طبقات التحقق من + تمكين طبقات التحقق لـ Vulkan Enable Vulkan Synchronization Validation - Vulkan تمكين التحقق من تزامن + تمكين التحقق من تزامن Vulkan Enable RenderDoc Debugging - RenderDoc تمكين تصحيح أخطاء + تمكين التصحيح باستخدام RenderDoc Enable Crash Diagnostics @@ -1628,19 +1628,19 @@ Collect Shaders - اجمع برامج التظليل + جمع الشيدرات Copy GPU Buffers - انسخ التخزين المؤقت لوحدة معالجة الرُسوم + نسخ مخازن الرسوميات Host Debug Markers - استضافة علامات التصحيح + علامات التصحيح على المضيف Guest Debug Markers - ضيف علامات التصحيح + علامات التصحيح على الضيف Update @@ -1648,11 +1648,11 @@ Check for Updates at Startup - تحقق من التحديثات عند بدء التشغيل + التحقق من التحديثات عند بدء التشغيل Always Show Changelog - اظهر سجل التغيرات دائماً + عرض سجل التغييرات دائمًا Update Channel @@ -1672,7 +1672,7 @@ Disable Trophy Notification - إغلاق إشعارات الميداليات + تعطيل إشعار التروفي Background Image @@ -1684,7 +1684,7 @@ Opacity - درجة السواد + الشفافية Play title music @@ -1692,7 +1692,7 @@ Update Compatibility Database On Startup - تحديث قاعدة بيانات التوافق عند التشغيل + تحديث بيانات التوافق تلقائيًا عند التشغيل Game Compatibility @@ -1700,7 +1700,7 @@ Display Compatibility Data - إظهار معلومات التوافق + عرض بيانات التوافق Update Compatibility Database @@ -1728,7 +1728,7 @@ Point your mouse at an option to display its description. - وجّه الماوس نحو خيار لعرض وصفه. + ✅ مرّر مؤشر الماوس على أي خِيار لعرض وصفه. Console Language:\nSets the language that the PS4 game uses.\nIt's recommended to set this to a language the game supports, which will vary by region. @@ -1736,11 +1736,11 @@ Emulator Language:\nSets the language of the emulator's user interface. - لغة المحاكي:\nتحدد لغة واجهة المستخدم الخاصة بالمحاكي. + لغة المحاكي:\nتحدد اللغة المستخدمة في واجهة المحاكي. Show Splash Screen:\nShows the game's splash screen (a special image) while the game is starting. - إظهار شاشة البداية:\nيعرض شاشة البداية الخاصة باللعبة (صورة خاصة) أثناء بدء التشغيل. + عرض شاشة البداية:\nيعرض شاشة البداية الخاصة باللعبة (صورة مميزة) أثناء بدء التشغيل. Enable Discord Rich Presence:\nDisplays the emulator icon and relevant information on your Discord profile. @@ -1748,59 +1748,60 @@ Username:\nSets the PS4's account username, which may be displayed by some games. - اسم المستخدم:\nيضبط اسم حساب PS4، الذي قد يتم عرضه في بعض الألعاب. + اسم المستخدم:\nيحدد اسم حساب'PS4، وقد يظهر في بعض الألعاب. Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. - مفتاح الميداليات:\nمفتاح يستخدم لفتح تشفير الميداليات. يجب أن يكون من جهاز مكسور الحماية.\nيجي أن يحتوي على أحرف نظام العد السداسي. + مفتاح الكؤوس:\nيُستخدم لفك تشفير الجوائز داخل الألعاب. يُستخرج من جهاز معدل.\nيجب أن يُكتب باستخدام رموز ست عشرية فقط. Log Type:\nSets whether to synchronize the output of the log window for performance. May have adverse effects on emulation. - نوع السجل:\nيضبط ما إذا كان سيتم مزامنة مخرجات نافذة السجل للأداء. قد يؤثر سلبًا على المحاكاة. + نوع السجل:\nييحدد ما إذا كان سيتم مزامنة مخرجات نافذة السجل لتحسين الأداء. قد يؤدي ذلك إلى تأثيرات سلبية على المحاكاة. Log Filter:\nFilters the log to only print specific information.\nExamples: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical"\nLevels: Trace, Debug, Info, Warning, Error, Critical - in this order, a specific level silences all levels preceding it in the list and logs every level after it. - فلتر السجل:\nيقوم بتصفية السجل لطباعة معلومات محددة فقط.\nأمثلة: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" المستويات: Trace, Debug, Info, Warning, Error, Critical - بالترتيب، مستوى محدد يخفي جميع المستويات التي تسبقه ويعرض جميع المستويات بعده. + تصفية السجل:\nيمكنك تحديد نوع المعلومات التي سيتم عرضها في السجل فقط.\nأمثلة: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" االمستويات حسب الترتيب:: Trace, Debug, Info, Warning, Error, Critical - عند اختيار مستوى معين، يتم تجاهل كل ما قبله، وتسجيل كل ما بعده. Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable. - تحديث: Release: إصدارات رسمية تصدر شهريًا، قد تكون قديمة بعض الشيء، لكنها أكثر استقرارًا واختبارًا. Nightly: إصدارات تطوير تحتوي على أحدث الميزات والإصلاحات، لكنها قد تحتوي على أخطاء وأقل استقرارًا. + تحديث: Release: نُسخ شهرية مستقرة وخضعت للاختبار، لكنها قد تكون قديمة. +Nightly: نُسخ تحتوي على أحدث الميزات، لكنها أقل استقرارًا وقد تحتوي على أخطاء. Background Image:\nControl the opacity of the game background image. - صورة الخلفية:\nيتحكم في درجة سواد صورة خلفية اللعبة. + صورة الخلفية:\nتحكم في شفافية صورة خلفية اللعبة. Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI. - تشغيل موسيقى العنوان:\nإذا كانت اللعبة تدعم ذلك، قم بتمكين تشغيل موسيقى خاصة عند اختيار اللعبة في واجهة المستخدم. + تشغيل موسيقى العنوان:\nفي حال كانت اللعبة تدعم ذلك، يتم تشغيل موسيقى خاصة عند تحديدها في الواجهة. Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window). - إغلاق نوافذ الميداليات المنبثقة:\n إغلاق إشعارات الميداليات داخل اللعبة. تقدم الميداليات يمكن تتبعه باستخدام عارض الميداليات (قم بالضغط على زر الفأرة الأيمن داخل النافذة الرئيسية). + تعطيل إشعارات التروفي:\nيمنع ظهور إشعارات الجوائز أثناء اللعب، بينما يظل بإمكانك متابعة التقدم من خلال "عارض التروفي" (انقر بزر الفأرة الأيمن على اللعبة في النافذة الرئيسية). Hide Cursor:\nChoose when the cursor will disappear:\nNever: You will always see the mouse.\nidle: Set a time for it to disappear after being idle.\nAlways: you will never see the mouse. - إخفاء المؤشر:\nاختر متى سيختفي المؤشر:\nأبداً: سترى الفأرة دائماً.\nعاطل: حدد وقتاً لاختفائه بعد أن يكون غير مستخدم.\nدائماً: لن ترى الفأرة أبداً. + إخفاء المؤشر:\nاختر متى يتم إخفاء مؤشر الماوس:\nأبدًا: يظهر دائمًا.\nعند الخمول: يختفي بعد فترة من عدم الحركة.\nدائمًا: لا يظهر إطلاقًا. Hide Idle Cursor Timeout:\nThe duration (seconds) after which the cursor that has been idle hides itself. - حدد وقتاً لاختفاء الفأرة بعد أن تكون غير مستخدم. + مدة إخفاء المؤشر عند الخمول:\nالوقت (بالثواني) الذي ينتظره المؤشر قبل أن يختفي تلقائيًا عند عدم استخدامه. Back Button Behavior:\nSets the controller's back button to emulate tapping the specified position on the PS4 touchpad. - سلوك زر العودة:\nيضبط زر العودة في وحدة التحكم ليحاكي الضغط على الموضع المحدد على لوحة اللمس في PS4. + سلوك زر الرجوع:\nيحدد وظيفة زر' الرجوع في وحدة التحكم لمحاكاة اللمس في موقع معيّن على لوحة اللمس الخاصة بـ PS4. Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information. - عرض بيانات التوافق:\nيقوم بإظهار معلومات توافق اللعبة في طريقة عرض الطاولة. تشغيل"تحديث التوافق عند التشغيل" للحصول على معلومات محدثة. + عرض بيانات التوافق:\nيعرض معلومات توافق الألعاب في عرض جدولي. فعّل ""تحديث التوافق عند بدء التشغيل"" للحصول على أحدث المعلومات. Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts. - تحديث التوافق عند التشغيل:\nتحديث قاعدة بيانات التوافق تلقائياً عند تشغيل shadps4. + تحديث التوافق عند بدء التشغيل:\nيتم تحديث قاعدة بيانات التوافق تلقائيًا عند بدء تشغيل shadPS4. Update Compatibility Database:\nImmediately update the compatibility database. - تحديث قاعدة بيانات التوافق:\nقم بتحديث قاعدة بيانات التوافق حالاً. + تحديث قاعدة بيانات التوافق:\nتحديث فوري لقاعدة بيانات التوافق. Never @@ -1816,15 +1817,15 @@ Touchpad Left - لوحة اللمس اليسرى + الجانب الأيسر من لوحة اللمس Touchpad Right - لوحة اللمس اليمنى + الجانب الأيمن من لوحة اللمس Touchpad Center - وسط لوحة اللمس + مركز لوحة اللمس None @@ -1832,11 +1833,11 @@ Graphics Device:\nOn multiple GPU systems, select the GPU the emulator will use from the drop down list,\nor select "Auto Select" to automatically determine it. - جهاز الرسومات:\nعلى الأنظمة متعددة وحدات معالجة الرسومات، اختر وحدة معالجة الرسومات التي سيستخدمها المحاكي من قائمة منسدلة،\nأو اختر "Auto Select" لتحديدها تلقائيًا. + جهاز الرسوميات:\nفي الأنظمة التي تحتوي على أكثر من معالج رسومي، اختر وحدة المعالجة الرسومية GPU التي سيستخدمها المحاكي من القائمة المنسدلة،\nأو اختر ""تحديد تلقائي"" ليتم اختيارها تلقائيًا. Width/Height:\nSets the size of the emulator window at launch, which can be resized during gameplay.\nThis is different from the in-game resolution. - العرض / الارتفاع:\nيضبط حجم نافذة المحاكي عند التشغيل، والذي يمكن تغيير حجمه أثناء اللعب.\nهذا يختلف عن دقة اللعبة نفسها. + العرض/الارتفاع:\nتحدد حجم نافذة المحاكي عند التشغيل، ويمكن تغيير حجمها أثناء اللعب.\nيختلف هذا عن دقة اللعبة داخل اللعبة. Vblank Divider:\nThe frame rate at which the emulator refreshes at is multiplied by this number. Changing this may have adverse effects, such as increasing the game speed, or breaking critical game functionality that does not expect this to change! @@ -1844,11 +1845,11 @@ Enable Shaders Dumping:\nFor the sake of technical debugging, saves the games shaders to a folder as they render. - تمكين تفريغ الـ Shaders:\nلأغراض تصحيح الأخطاء التقنية، يحفظ الـ Shaders الخاصة باللعبة في مجلد أثناء التشغيل. + تمكين تفريغ الشيدرات:\nلأغراض تصحيح الأخطاء التقنية، يقوم بحفظ شيدرات اللعبة في مجلد أثناء عرضها. Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card. - تمكين GPU الافتراضية:\nلأغراض تصحيح الأخطاء التقنية، يقوم بتعطيل عرض اللعبة كما لو لم يكن هناك بطاقة رسومات. + تمكين GPU فارغ:\nلأغراض تصحيح الأخطاء التقنية، يتم تعطيل عرض اللعبة كما لو لم يكن هناك كرت شاشة. Enable HDR:\nEnables HDR in games that support it.\nYour monitor must have support for the BT2020 PQ color space and the RGB10A2 swapchain format. @@ -1856,7 +1857,7 @@ Game Folders:\nThe list of folders to check for installed games. - مجلدات اللعبة:\nقائمة بالمجلدات للتحقق من الألعاب المثبتة. + مجلدات اللعبة:\nقائمة المجلدات التي يتم فحصها للبحث عن الألعاب المثبتة. Add:\nAdd a folder to the list. @@ -1868,7 +1869,7 @@ Enable Debug Dumping:\nSaves the import and export symbols and file header information of the currently running PS4 program to a directory. - تمكين تفريغ التصحيح:\nيحفظ رموز الاستيراد والتصدير ومعلومات رأس الملف للبرنامج الحالي لجهاز PS4 إلى دليل. + تمكين تفريغ التصحيح:\nيقوم بحفظ الرموز المستوردة والمصدرة، بالإضافة إلى معلومات رأس الملف للبرنامج الجاري تشغيله على PS4 في مجلد. Enable Vulkan Validation Layers:\nEnables a system that validates the state of the Vulkan renderer and logs information about its internal state.\nThis will reduce performance and likely change the behavior of emulation. @@ -1980,11 +1981,11 @@ W: - W: + العرض: H: - H: + الارتفاع: Separate Log Files @@ -2055,7 +2056,7 @@ TrophyViewer Trophy Viewer - عارض الجوائز + عارض التروفي Select Game: diff --git a/src/qt_gui/translations/it_IT.ts b/src/qt_gui/translations/it_IT.ts index 908013004..8c9e53611 100644 --- a/src/qt_gui/translations/it_IT.ts +++ b/src/qt_gui/translations/it_IT.ts @@ -138,7 +138,7 @@ File Exists - Il file è presente + Il file esiste già File already exists. Do you want to replace it? From 703620c7cd17d336f78ff897c66b3d48e448b0b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A5IGA?= <164882787+Xphalnos@users.noreply.github.com> Date: Thu, 17 Apr 2025 08:43:14 +0200 Subject: [PATCH 11/41] [Windows] Adding Properties to the Executable (#2789) --- CMakeLists.txt | 9 ++++++++- src/shadps4.rc | 44 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ea8688df..76e7cb0ee 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,14 @@ execute_process( OUTPUT_STRIP_TRAILING_WHITESPACE ) -set(APP_VERSION "0.7.1 WIP") +# Set Version +set(EMULATOR_VERSION_MAJOR "0") +set(EMULATOR_VERSION_MINOR "7") +set(EMULATOR_VERSION_PATCH "1") + +set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}") + +set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP") set(APP_IS_RELEASE false) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY) diff --git a/src/shadps4.rc b/src/shadps4.rc index 8c984f260..9edccfbfd 100644 --- a/src/shadps4.rc +++ b/src/shadps4.rc @@ -1 +1,43 @@ -IDI_ICON1 ICON "images/shadps4.ico" \ No newline at end of file +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "winresrc.h" + +#define xstr(s) str(s) +#define str(s) #s + +// NEUTRAL LANG +LANGUAGE LANG_NEUTRAL, 0x8 + +// ICON +IDI_ICON1 ICON "images/shadps4.ico" + +// VERSION +VS_VERSION_INFO VERSIONINFO + FILEVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0 + PRODUCTVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0 + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "shadPS4 - PlayStation 4 Emulator\0" + VALUE "FileVersion", xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) "." xstr(EMULATOR_VERSION_PATCH) ".0\0" + VALUE "InternalName", "shadPS4\0" + VALUE "LegalCopyright", "Copyright 2025 shadPS4 Team\0" + VALUE "OriginalFilename", "shadPS4.exe\0" + VALUE "ProductName", "shadPS4\0" + VALUE "ProductVersion", xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) "." xstr(EMULATOR_VERSION_PATCH) ".0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END From df89241eb81c9512f348ba066c5c52a8984b3bbf Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Thu, 17 Apr 2025 13:04:48 -0700 Subject: [PATCH 12/41] vk_rasterizer: Improve viewport depth calculations. (#2799) --- .../renderer_vulkan/vk_rasterizer.cpp | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index f8d09f011..b04b4a07e 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -999,16 +999,13 @@ void Rasterizer::UpdateViewportScissorState() const { boost::container::static_vector viewports; boost::container::static_vector scissors; - const auto& vp_ctl = regs.viewport_control; - const float reduce_z = - regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW ? 1.0f : 0.0f; - if (regs.polygon_control.enable_window_offset && (regs.window_offset.window_x_offset != 0 || regs.window_offset.window_y_offset != 0)) { LOG_ERROR(Render_Vulkan, "PA_SU_SC_MODE_CNTL.VTX_WINDOW_OFFSET_ENABLE support is not yet implemented."); } + const auto& vp_ctl = regs.viewport_control; for (u32 i = 0; i < Liverpool::NumViewports; i++) { const auto& vp = regs.viewports[i]; const auto& vp_d = regs.viewport_depths[i]; @@ -1019,16 +1016,32 @@ void Rasterizer::UpdateViewportScissorState() const { const auto zoffset = vp_ctl.zoffset_enable ? vp.zoffset : 0.f; const auto zscale = vp_ctl.zscale_enable ? vp.zscale : 1.f; - vk::Viewport viewport = { - .minDepth = zoffset - zscale * reduce_z, - .maxDepth = zscale + zoffset, - }; + vk::Viewport viewport{}; + + // https://gitlab.freedesktop.org/mesa/mesa/-/blob/209a0ed/src/amd/vulkan/radv_pipeline_graphics.c#L688-689 + // https://gitlab.freedesktop.org/mesa/mesa/-/blob/209a0ed/src/amd/vulkan/radv_cmd_buffer.c#L3103-3109 + // When the clip space is ranged [-1...1], the zoffset is centered. + // By reversing the above viewport calculations, we get the following: + if (regs.clipper_control.clip_space == AmdGpu::Liverpool::ClipSpace::MinusWToW) { + viewport.minDepth = zoffset - zscale; + viewport.maxDepth = zoffset + zscale; + } else { + viewport.minDepth = zoffset; + viewport.maxDepth = zoffset + zscale; + } + + if (!regs.depth_render_override.disable_viewport_clamp) { + // Apply depth clamp. + viewport.minDepth = std::max(viewport.minDepth, vp_d.zmin); + viewport.maxDepth = std::min(viewport.maxDepth, vp_d.zmax); + } + if (!instance.IsDepthRangeUnrestrictedSupported()) { - // Unrestricted depth range not supported by device. Make best attempt - // by restricting to valid range. + // Unrestricted depth range not supported by device. Restrict to valid range. viewport.minDepth = std::max(viewport.minDepth, 0.f); viewport.maxDepth = std::min(viewport.maxDepth, 1.f); } + if (regs.IsClipDisabled()) { // In case if clipping is disabled we patch the shader to convert vertex position // from screen space coordinates to NDC by defining a render space as full hardware @@ -1048,6 +1061,7 @@ void Rasterizer::UpdateViewportScissorState() const { viewport.width = xscale * 2.0f; viewport.height = yscale * 2.0f; } + viewports.push_back(viewport); auto vp_scsr = scsr; From 20b11f2d63353c8f7c10a7d1ae1f180e9a96e172 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Fri, 18 Apr 2025 03:00:14 -0500 Subject: [PATCH 13/41] libkernel: Fix sceKernelAllocateDirectMemory and sceKernelAvailableDirectMemorySize (#2803) * AllocateDirectMemory fixes search_start and search_end were ignored in certain cases, this fixes that issue. I've also basically rewritten the function in the process, since the lack of documentation made it difficult to make the proper adjustments. * DirectQueryAvailable fixes remaining_size was calculated incorrectly in cases where a free dmem_area had a base earlier than search_start, or an end after search_end. * Reduce sceKernelGetDirectMemorySize log severity By this point, we've confirmed that sceKernelGetDirectMemorySize is hardware-accurate. There's no reason to clog logs with this function, which games usually call before every sceKernelAllocateDirectMemory call. * Clang * Fix phys_addr_out phys_addr_out should be equal to search_start in cases where search_start is greater than the dmem_area base. * Dividing by zero is fun Need to check for alignment when aligning things. * Update memory.cpp * Clang --- src/core/libraries/kernel/memory.cpp | 2 +- src/core/memory.cpp | 65 ++++++++++++++++++---------- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 7b3ac5646..cbc5ad77e 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -19,7 +19,7 @@ namespace Libraries::Kernel { u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() { - LOG_WARNING(Kernel_Vmm, "called"); + LOG_TRACE(Kernel_Vmm, "called"); const auto* memory = Core::Memory::Instance(); return memory->GetTotalDirectSize(); } diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 8b108a654..f88cede4e 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -139,35 +139,35 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, alignment = alignment > 0 ? alignment : 16_KB; auto dmem_area = FindDmemArea(search_start); + auto mapping_start = search_start > dmem_area->second.base + ? Common::AlignUp(search_start, alignment) + : Common::AlignUp(dmem_area->second.base, alignment); + auto mapping_end = Common::AlignUp(mapping_start + size, alignment); - const auto is_suitable = [&] { - if (dmem_area == dmem_map.end()) { - return false; - } - const auto aligned_base = Common::AlignUp(dmem_area->second.base, alignment); - const auto alignment_size = aligned_base - dmem_area->second.base; - const auto remaining_size = - dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; - return dmem_area->second.is_free && remaining_size >= size; - }; - while (dmem_area != dmem_map.end() && !is_suitable() && - dmem_area->second.GetEnd() <= search_end) { - ++dmem_area; + // Find the first free, large enough dmem area in the range. + while ((!dmem_area->second.is_free || dmem_area->second.GetEnd() < mapping_end) && + dmem_area != dmem_map.end()) { + // The current dmem_area isn't suitable, move to the next one. + dmem_area++; + + // Update local variables based on the new dmem_area + mapping_start = search_start > dmem_area->second.base + ? Common::AlignUp(search_start, alignment) + : Common::AlignUp(dmem_area->second.base, alignment); + mapping_end = Common::AlignUp(mapping_start + size, alignment); } - if (!is_suitable()) { + + if (dmem_area == dmem_map.end()) { + // There are no suitable mappings in this range LOG_ERROR(Kernel_Vmm, "Unable to find free direct memory area: size = {:#x}", size); return -1; } - // Align free position - PAddr free_addr = dmem_area->second.base; - free_addr = Common::AlignUp(free_addr, alignment); - // Add the allocated region to the list and commit its pages. - auto& area = CarveDmemArea(free_addr, size)->second; + auto& area = CarveDmemArea(mapping_start, size)->second; area.memory_type = memory_type; area.is_free = false; - return free_addr; + return mapping_start; } void MemoryManager::Free(PAddr phys_addr, size_t size) { @@ -632,17 +632,34 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si auto dmem_area = FindDmemArea(search_start); PAddr paddr{}; size_t max_size{}; - while (dmem_area != dmem_map.end() && dmem_area->second.GetEnd() <= search_end) { + + while (dmem_area != dmem_map.end()) { if (!dmem_area->second.is_free) { dmem_area++; continue; } - const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) - : dmem_area->second.base; + auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) + : dmem_area->second.base; const auto alignment_size = aligned_base - dmem_area->second.base; - const auto remaining_size = + auto remaining_size = dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; + + if (dmem_area->second.base < search_start) { + // We need to trim remaining_size to ignore addresses before search_start + remaining_size = remaining_size > (search_start - dmem_area->second.base) + ? remaining_size - (search_start - dmem_area->second.base) + : 0; + aligned_base = alignment > 0 ? Common::AlignUp(search_start, alignment) : search_start; + } + + if (dmem_area->second.GetEnd() > search_end) { + // We need to trim remaining_size to ignore addresses beyond search_end + remaining_size = remaining_size > (search_start - dmem_area->second.base) + ? remaining_size - (dmem_area->second.GetEnd() - search_end) + : 0; + } + if (remaining_size > max_size) { paddr = aligned_base; max_size = remaining_size; From 23c616c647a20c5c5f0f8a5785af003460e50ba9 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Fri, 18 Apr 2025 22:41:13 +0200 Subject: [PATCH 14/41] why was this hardcoded in this one specific place (#2809) --- src/qt_gui/kbm_gui.cpp | 55 +++--------------------------------------- 1 file changed, 3 insertions(+), 52 deletions(-) diff --git a/src/qt_gui/kbm_gui.cpp b/src/qt_gui/kbm_gui.cpp index 8777dda95..2e1f6ddce 100644 --- a/src/qt_gui/kbm_gui.cpp +++ b/src/qt_gui/kbm_gui.cpp @@ -127,58 +127,9 @@ tr("Do you want to overwrite existing mappings with the mappings from the Common } void KBMSettings::ButtonConnects() { - connect(ui->CrossButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->CrossButton); }); - connect(ui->CircleButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->CircleButton); }); - connect(ui->TriangleButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->TriangleButton); }); - connect(ui->SquareButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->SquareButton); }); - - connect(ui->L1Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L1Button); }); - connect(ui->L2Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L2Button); }); - connect(ui->L3Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->L3Button); }); - connect(ui->R1Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R1Button); }); - connect(ui->R2Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R2Button); }); - connect(ui->R3Button, &QPushButton::clicked, this, [this]() { StartTimer(ui->R3Button); }); - - connect(ui->TouchpadButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->TouchpadButton); }); - connect(ui->OptionsButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->OptionsButton); }); - - connect(ui->DpadUpButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->DpadUpButton); }); - connect(ui->DpadDownButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->DpadDownButton); }); - connect(ui->DpadLeftButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->DpadLeftButton); }); - connect(ui->DpadRightButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->DpadRightButton); }); - - connect(ui->LStickUpButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->LStickUpButton); }); - connect(ui->LStickDownButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->LStickDownButton); }); - connect(ui->LStickLeftButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->LStickLeftButton); }); - connect(ui->LStickRightButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->LStickRightButton); }); - - connect(ui->RStickUpButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->RStickUpButton); }); - connect(ui->RStickDownButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->RStickDownButton); }); - connect(ui->RStickLeftButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->RStickLeftButton); }); - connect(ui->RStickRightButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->RStickRightButton); }); - - connect(ui->LHalfButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->LHalfButton); }); - connect(ui->RHalfButton, &QPushButton::clicked, this, - [this]() { StartTimer(ui->RHalfButton); }); + for (auto& button : ButtonsList) { + connect(button, &QPushButton::clicked, this, [this, &button]() { StartTimer(button); }); + } } void KBMSettings::DisableMappingButtons() { From 0feb2e7211bb4cb5cedfd6a1363e42b505b628b2 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Fri, 18 Apr 2025 15:41:33 -0500 Subject: [PATCH 15/41] Emulate memory behavior of libSceGnmDriver initialization (#2807) * Emulate memory behavior of libSceGnmDriver _DT_INIT Due to the unique way some games check for sceKernelAllocateDirectMemory failures, emulating this properly is necessary. * Clang * Fix address input for direct memory call * Fix bug with DirectQueryAvailable Missed this in my prior PR. * DirectQueryAvailable fix Fixes error cases to be more hardware accurate. --- src/core/libraries/gnmdriver/gnmdriver.cpp | 2 +- src/core/libraries/kernel/memory.cpp | 6 ------ src/core/linker.cpp | 16 ++++++++++++++-- src/core/memory.cpp | 2 +- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index e8560b2b8..25ac4921c 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -2804,7 +2804,7 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { liverpool = std::make_unique(); presenter = std::make_unique(*g_window, liverpool.get()); - const int result = sceKernelGetCompiledSdkVersion(&sdk_version); + const s32 result = sceKernelGetCompiledSdkVersion(&sdk_version); if (result != ORBIS_OK) { sdk_version = 0; } diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index cbc5ad77e..8a0c91479 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -106,12 +106,6 @@ s32 PS4_SYSV_ABI sceKernelAvailableDirectMemorySize(u64 searchStart, u64 searchE if (physAddrOut == nullptr || sizeOut == nullptr) { return ORBIS_KERNEL_ERROR_EINVAL; } - if (searchEnd > sceKernelGetDirectMemorySize()) { - return ORBIS_KERNEL_ERROR_EINVAL; - } - if (searchEnd <= searchStart) { - return ORBIS_KERNEL_ERROR_ENOMEM; - } auto* memory = Core::Memory::Instance(); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 4ccb9d943..69deb464f 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -108,10 +108,22 @@ void Linker::Execute(const std::vector args) { static constexpr s64 InternalMemorySize = 0x1000000; void* addr_out{reinterpret_cast(KernelAllocBase)}; - const s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory( - &addr_out, InternalMemorySize, 3, 0, "SceKernelInternalMemory"); + s32 ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory(&addr_out, InternalMemorySize, 3, + 0, "SceKernelInternalMemory"); ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping"); + // Simulate libSceGnmDriver initialization, which maps a chunk of direct memory. + // Some games fail without accurately emulating this behavior. + s64 phys_addr{}; + ret = Libraries::Kernel::sceKernelAllocateDirectMemory( + 0, Libraries::Kernel::sceKernelGetDirectMemorySize(), 0x10000, 0x10000, 3, &phys_addr); + if (ret == 0) { + void* addr{reinterpret_cast(0xfe0000000)}; + ret = Libraries::Kernel::sceKernelMapNamedDirectMemory(&addr, 0x10000, 0x13, 0, phys_addr, + 0x10000, "SceGnmDriver"); + } + ASSERT_MSG(ret == 0, "Unable to emulate libSceGnmDriver initialization"); + main_thread.Run([this, module, args](std::stop_token) { Common::SetCurrentThreadName("GAME_MainThread"); LoadSharedLibraries(); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index f88cede4e..cb80d6be4 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -655,7 +655,7 @@ int MemoryManager::DirectQueryAvailable(PAddr search_start, PAddr search_end, si if (dmem_area->second.GetEnd() > search_end) { // We need to trim remaining_size to ignore addresses beyond search_end - remaining_size = remaining_size > (search_start - dmem_area->second.base) + remaining_size = remaining_size > (dmem_area->second.GetEnd() - search_end) ? remaining_size - (dmem_area->second.GetEnd() - search_end) : 0; } From 81ada41baa113da41446e093041ca5066c9b5409 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Fri, 18 Apr 2025 22:42:17 +0200 Subject: [PATCH 16/41] NpAuth library stub (#2808) * Add the NpAuth library * clang * you didn't see anything * Add some random return to make games at least start using this library * i'm once again asking for your continued ignorance of what i'm forgetting to not push * debug logging * apparently just this is still enough * this isn't used but it still shouldn't be incorrect --- CMakeLists.txt | 2 + src/common/logging/filter.cpp | 1 + src/common/logging/types.h | 1 + src/core/libraries/libs.cpp | 2 + src/core/libraries/np_auth/np_auth.cpp | 99 ++++++++++++++++++++++++++ src/core/libraries/np_auth/np_auth.h | 29 ++++++++ 6 files changed, 134 insertions(+) create mode 100644 src/core/libraries/np_auth/np_auth.cpp create mode 100644 src/core/libraries/np_auth/np_auth.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 76e7cb0ee..beea8a1e0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -570,6 +570,8 @@ set(NP_LIBS src/core/libraries/np_common/np_common.cpp src/core/libraries/np_web_api/np_web_api.h src/core/libraries/np_party/np_party.cpp src/core/libraries/np_party/np_party.h + src/core/libraries/np_auth/np_auth.cpp + src/core/libraries/np_auth/np_auth.h ) set(ZLIB_LIB src/core/libraries/zlib/zlib.cpp diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index bed7802ed..867d62916 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -101,6 +101,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, Ssl2) \ SUB(Lib, SysModule) \ SUB(Lib, Move) \ + SUB(Lib, NpAuth) \ SUB(Lib, NpCommon) \ SUB(Lib, NpManager) \ SUB(Lib, NpScore) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index c07efbc0d..e5714a81a 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -69,6 +69,7 @@ enum class Class : u8 { Lib_Http2, ///< The LibSceHttp2 implementation. Lib_SysModule, ///< The LibSceSysModule implementation Lib_NpCommon, ///< The LibSceNpCommon implementation + Lib_NpAuth, ///< The LibSceNpAuth implementation Lib_NpManager, ///< The LibSceNpManager implementation Lib_NpScore, ///< The LibSceNpScore implementation Lib_NpTrophy, ///< The LibSceNpTrophy implementation diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index d0f82556e..3f5baf640 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -27,6 +27,7 @@ #include "core/libraries/network/netctl.h" #include "core/libraries/network/ssl.h" #include "core/libraries/network/ssl2.h" +#include "core/libraries/np_auth/np_auth.h" #include "core/libraries/np_common/np_common.h" #include "core/libraries/np_manager/np_manager.h" #include "core/libraries/np_party/np_party.h" @@ -88,6 +89,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::NpScore::RegisterlibSceNpScore(sym); Libraries::NpTrophy::RegisterlibSceNpTrophy(sym); Libraries::NpWebApi::RegisterlibSceNpWebApi(sym); + Libraries::NpAuth::RegisterlibSceNpAuth(sym); Libraries::ScreenShot::RegisterlibSceScreenShot(sym); Libraries::AppContent::RegisterlibSceAppContent(sym); Libraries::PngDec::RegisterlibScePngDec(sym); diff --git a/src/core/libraries/np_auth/np_auth.cpp b/src/core/libraries/np_auth/np_auth.cpp new file mode 100644 index 000000000..9ec986f3c --- /dev/null +++ b/src/core/libraries/np_auth/np_auth.cpp @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" +#include "core/libraries/np_auth/np_auth.h" + +namespace Libraries::NpAuth { + +s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCode() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthGetIdToken() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthAbortRequest() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthCreateAsyncRequest() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthCreateRequest() { + LOG_WARNING(Lib_NpAuth, "(DUMMY) called"); + return 1; +} + +s32 PS4_SYSV_ABI sceNpAuthDeleteRequest(s32 id) { + LOG_WARNING(Lib_NpAuth, "(DUMMY) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeA() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeV3() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthGetIdTokenA() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthGetIdTokenV3() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthPollAsync() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthSetTimeout() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceNpAuthWaitAsync() { + LOG_ERROR(Lib_NpAuth, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("KxGkOrQJTqY", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1, + sceNpAuthGetAuthorizationCode); + LIB_FUNCTION("uaB-LoJqHis", "libSceNpAuthCompat", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdToken); + LIB_FUNCTION("cE7wIsqXdZ8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthAbortRequest); + LIB_FUNCTION("N+mr7GjTvr8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, + sceNpAuthCreateAsyncRequest); + LIB_FUNCTION("6bwFkosYRQg", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthCreateRequest); + LIB_FUNCTION("H8wG9Bk-nPc", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthDeleteRequest); + LIB_FUNCTION("KxGkOrQJTqY", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, + sceNpAuthGetAuthorizationCode); + LIB_FUNCTION("qAUXQ9GdWp8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, + sceNpAuthGetAuthorizationCodeA); + LIB_FUNCTION("KI4dHLlTNl0", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, + sceNpAuthGetAuthorizationCodeV3); + LIB_FUNCTION("uaB-LoJqHis", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdToken); + LIB_FUNCTION("CocbHVIKPE8", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdTokenA); + LIB_FUNCTION("RdsFVsgSpZY", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthGetIdTokenV3); + LIB_FUNCTION("gjSyfzSsDcE", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthPollAsync); + LIB_FUNCTION("PM3IZCw-7m0", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthSetTimeout); + LIB_FUNCTION("SK-S7daqJSE", "libSceNpAuth", 1, "libSceNpAuth", 1, 1, sceNpAuthWaitAsync); +}; + +} // namespace Libraries::NpAuth \ No newline at end of file diff --git a/src/core/libraries/np_auth/np_auth.h b/src/core/libraries/np_auth/np_auth.h new file mode 100644 index 000000000..a6a66b452 --- /dev/null +++ b/src/core/libraries/np_auth/np_auth.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::NpAuth { + +s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCode(); +s32 PS4_SYSV_ABI sceNpAuthGetIdToken(); +s32 PS4_SYSV_ABI sceNpAuthAbortRequest(); +s32 PS4_SYSV_ABI sceNpAuthCreateAsyncRequest(); +s32 PS4_SYSV_ABI sceNpAuthCreateRequest(); +s32 PS4_SYSV_ABI sceNpAuthDeleteRequest(s32 id); +s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeA(); +s32 PS4_SYSV_ABI sceNpAuthGetAuthorizationCodeV3(); +s32 PS4_SYSV_ABI sceNpAuthGetIdTokenA(); +s32 PS4_SYSV_ABI sceNpAuthGetIdTokenV3(); +s32 PS4_SYSV_ABI sceNpAuthPollAsync(); +s32 PS4_SYSV_ABI sceNpAuthSetTimeout(); +s32 PS4_SYSV_ABI sceNpAuthWaitAsync(); + +void RegisterlibSceNpAuth(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::NpAuth \ No newline at end of file From 6e963a7f7154ada20533d5efa3f705ffc5005c76 Mon Sep 17 00:00:00 2001 From: Missake212 Date: Fri, 18 Apr 2025 21:42:48 +0100 Subject: [PATCH 17/41] Changing the maximum amount of contributors on the README (#2804) * Update README.md * Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0e2248970..ba0fe225d 100644 --- a/README.md +++ b/README.md @@ -166,11 +166,11 @@ Open a PR and we'll check it :) # Translations -If you want to translate shadPS4 to your language we use [**crowdin**](https://crowdin.com/project/shadps4-emulator). +If you want to translate shadPS4 to your language we use [**Crowdin**](https://crowdin.com/project/shadps4-emulator). # Contributors - + From e11ffe242bcc7fe41dc6ee817a8acfb614b176a6 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 18 Apr 2025 23:47:59 +0300 Subject: [PATCH 18/41] Update team member on readme --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ba0fe225d..e24d57807 100644 --- a/README.md +++ b/README.md @@ -146,16 +146,13 @@ The following firmware modules are supported and must be placed in shadPS4's `us # Main team - [**georgemoralis**](https://github.com/georgemoralis) -- [**raphaelthegreat**](https://github.com/raphaelthegreat) - [**psucien**](https://github.com/psucien) -- [**skmp**](https://github.com/skmp) -- [**wheremyfoodat**](https://github.com/wheremyfoodat) -- [**raziel1000**](https://github.com/raziel1000) - [**viniciuslrangel**](https://github.com/viniciuslrangel) - [**roamic**](https://github.com/vladmikhalin) -- [**poly**](https://github.com/polybiusproxy) - [**squidbus**](https://github.com/squidbus) - [**frodo**](https://github.com/baggins183) +- [**Stephen Miller**](https://github.com/StevenMiller123) +- [**kalaposfos13**](https://github.com/kalaposfos13) Logo is done by [**Xphalnos**](https://github.com/Xphalnos) From d0dbb737d9a87e2ea745e0d0b282c795beb62104 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 19 Apr 2025 17:51:43 +0300 Subject: [PATCH 19/41] New translations en_us.ts (Arabic) (#2810) --- src/qt_gui/translations/ar_SA.ts | 38 ++++++++++++++++---------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/qt_gui/translations/ar_SA.ts b/src/qt_gui/translations/ar_SA.ts index 7ef3c6171..e434b3259 100644 --- a/src/qt_gui/translations/ar_SA.ts +++ b/src/qt_gui/translations/ar_SA.ts @@ -66,7 +66,7 @@ You can delete the cheats you don't want after downloading them. - يمكنك حذف الشفرات التي لا تريدها بعد تنزيلها. + يمكنك حذف الشفرات التي لا 'تريدها بعد تنزيلها. Do you want to delete the selected file?\n%1 @@ -74,11 +74,11 @@ Select Patch File: - إختر ملف الباتش: + اختر مِلَف التصحيح: Download Patches - تحميل الباتشات + تحميل ملفات التصحيح Save @@ -98,15 +98,15 @@ No patch selected. - لم يتم اختيار أي تصحيح. + لم يتم تحديد أي مِلَف تصحيح. Unable to open files.json for reading. - تعذر فتح files.json للقراءة. + تعذّر فتح مِلَف files.json للقراءة. No patch file found for the current serial. - لم يتم العثور على مِلَفّ باتش للسيريال الحالي. + لم يتم العثور على مِلَف تصحيح للسيريال الحالي. Unable to open the file for reading. @@ -126,11 +126,11 @@ Options saved successfully. - تم حفظ الخيارات بنجاح. + تم حفظ الإعدادات. Invalid Source - مصدر غير صالح + المصدر غير صالح The selected source is invalid. @@ -138,11 +138,11 @@ File Exists - الملف موجود + المِلَف موجود مسبقًا File already exists. Do you want to replace it? - يوجد ملف بنفس الاسم. هل ترغب في استبداله؟ + المِلَف موجود مسبقًا. هل ترغب في استبداله؟ Failed to save file: @@ -158,7 +158,7 @@ No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. - لم يتم العثور على شفرات لهذه اللعبة في هذه النسخة من المستودع المحدد. حاول استخدام مستودع آخر أو نسخة مختلفة من اللعبة. + لم يتم العثور على شفرات لهذه اللعبة في هذا الإصدار من المستودع المحدد. جرّب مستودعًا آخر أو إصدارًا مختلفًا من اللعبة. Cheats Downloaded Successfully @@ -182,7 +182,7 @@ Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. - تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات لجميع الألعاب، ولا داعي لتنزيلها بشكل فردي لكل لعبة كما هو الحال مع الغش. إذا لم يظهر التحديث، قد يكون السبب أنه غير متوفر للإصدار وسيريال اللعبة المحدد. + تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات المتوفرة لجميع الألعاب، ولا حاجة إلى تنزيلها بشكل فردي لكل لعبة كما هو الحال مع الشفرات. إذا لم يظهر التصحيح، فقد لا يكون متوفرًا للسيريال أو الإصدار المحدد من اللعبة. Failed to parse JSON data from HTML. @@ -190,15 +190,15 @@ Failed to retrieve HTML page. - .HTML فشل في استرجاع صفحة + فشل في جلب صفحة HTML. The game is in version: %1 - النسخة الحالية للعبة هي: %1 + إصدار اللعبة الحالي: %1 The downloaded patch only works on version: %1 - الباتش الذي تم تنزيله يعمل فقط على الإصدار: %1 + التصحيح الذي تم تنزيله يعمل فقط مع الإصدار:%1 You may need to update your game. @@ -206,7 +206,7 @@ Incompatibility Notice - إشعار عدم التوافق + إشعار بعدم التوافق Failed to open file: @@ -238,7 +238,7 @@ Can't apply cheats before the game is started - لا يمكن تطبيق الغش قبل بدء اللعبة. + لا 'يمكن تطبيق الشفرات قبل بَدْء اللعبة Close @@ -249,7 +249,7 @@ CheckUpdate Auto Updater - محدث تلقائي + التحديثات التلقائية Error @@ -261,7 +261,7 @@ The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. - يتيح التحديث التلقائي ما يصل إلى 60 عملية تحقق من التحديث في الساعة.\nلقد وصلت إلى هذا الحد. الرجاء المحاولة مرة أخرى لاحقًا. + تسمح التحديثات التلقائية بـ 60 عملية تحقق من التحديث في الساعة.\nلقد وصلت إلى الحد المسموح به. الرجاء المحاولة لاحقًا. Failed to parse update information. From d188510e59aeef73aa7ca7076cf53e5a6e5d2ab6 Mon Sep 17 00:00:00 2001 From: Missake212 Date: Sat, 19 Apr 2025 15:51:59 +0100 Subject: [PATCH 20/41] Discord logo fix on the README. (#2811) * Fix the broken Discord logo on the README * Update README.md change the size to match better --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e24d57807..985bba586 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later

- + From 111ff2bedd2cc8797d52a8be786245eada9ed2ad Mon Sep 17 00:00:00 2001 From: bigqy <52437374+bigQY@users.noreply.github.com> Date: Sat, 19 Apr 2025 22:52:43 +0800 Subject: [PATCH 21/41] =?UTF-8?q?Fixe:=20Updated=20the=20timing=20of=20set?= =?UTF-8?q?ting=20text=20translation=20for=20the=20=E2=80=9CShow=20label?= =?UTF-8?q?=20under=20icon=E2=80=9D=20action=20in=20the=20toolbar=20to=20s?= =?UTF-8?q?et=20the=20text=20after=20retranslateUi.=20(#2806)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/qt_gui/main_window_ui.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 2c4d4480b..518f860b0 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -106,8 +106,6 @@ public: toggleLabelsAct = new QAction(MainWindow); toggleLabelsAct->setObjectName("toggleLabelsAct"); - toggleLabelsAct->setText( - QCoreApplication::translate("MainWindow", "Show Labels Under Icons")); toggleLabelsAct->setCheckable(true); toggleLabelsAct->setChecked(Config::getShowLabelsUnderIcons()); @@ -413,6 +411,7 @@ public: setThemeTokyoNight->setText("Tokyo Night"); setThemeOled->setText("OLED"); toolBar->setWindowTitle(QCoreApplication::translate("MainWindow", "toolBar", nullptr)); + toggleLabelsAct->setText(QCoreApplication::translate("MainWindow", "Show Labels Under Icons")); } // retranslateUi }; From 69777e2ffac74477f97febe0f2705e4cf989cff3 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Sat, 19 Apr 2025 17:19:40 +0200 Subject: [PATCH 22/41] hotfix: clang-format --- src/qt_gui/main_window_ui.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 518f860b0..4d3481c07 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -411,7 +411,8 @@ public: setThemeTokyoNight->setText("Tokyo Night"); setThemeOled->setText("OLED"); toolBar->setWindowTitle(QCoreApplication::translate("MainWindow", "toolBar", nullptr)); - toggleLabelsAct->setText(QCoreApplication::translate("MainWindow", "Show Labels Under Icons")); + toggleLabelsAct->setText( + QCoreApplication::translate("MainWindow", "Show Labels Under Icons")); } // retranslateUi }; From 5be726ca3b311a3fd780efb8d9bd2e7b06349430 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sun, 20 Apr 2025 10:26:52 -0500 Subject: [PATCH 23/41] Revert libSceGnmDriver initialization emulation (#2816) Under normal circumstances, this mapping should only occur when libSceGnmDriver initializes. From what I can tell, this can be after game code starts running. Until there's a better way to accurately handle this, allocating this memory breaks some games. This revert fixes the regression in games using the GFD engine. --- src/core/linker.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 69deb464f..0f86376af 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -112,18 +112,6 @@ void Linker::Execute(const std::vector args) { 0, "SceKernelInternalMemory"); ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping"); - // Simulate libSceGnmDriver initialization, which maps a chunk of direct memory. - // Some games fail without accurately emulating this behavior. - s64 phys_addr{}; - ret = Libraries::Kernel::sceKernelAllocateDirectMemory( - 0, Libraries::Kernel::sceKernelGetDirectMemorySize(), 0x10000, 0x10000, 3, &phys_addr); - if (ret == 0) { - void* addr{reinterpret_cast(0xfe0000000)}; - ret = Libraries::Kernel::sceKernelMapNamedDirectMemory(&addr, 0x10000, 0x13, 0, phys_addr, - 0x10000, "SceGnmDriver"); - } - ASSERT_MSG(ret == 0, "Unable to emulate libSceGnmDriver initialization"); - main_thread.Run([this, module, args](std::stop_token) { Common::SetCurrentThreadName("GAME_MainThread"); LoadSharedLibraries(); From 0c86c54d48533e3505e56e639059d28331fe4bc3 Mon Sep 17 00:00:00 2001 From: Fire Cube Date: Mon, 21 Apr 2025 23:25:15 +0200 Subject: [PATCH 24/41] Implement SET_PC_B64 instruction (#2823) * basic impl * minor improvements * clang * more clang * improvements requested by squidbus --- .../frontend/control_flow_graph.cpp | 63 ++++++++++++++++++- .../frontend/instruction.cpp | 2 +- .../frontend/translate/scalar_flow.cpp | 1 + 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/shader_recompiler/frontend/control_flow_graph.cpp b/src/shader_recompiler/frontend/control_flow_graph.cpp index cf1882b8c..b53db9e94 100644 --- a/src/shader_recompiler/frontend/control_flow_graph.cpp +++ b/src/shader_recompiler/frontend/control_flow_graph.cpp @@ -4,6 +4,7 @@ #include #include #include "common/assert.h" +#include "common/logging/log.h" #include "shader_recompiler/frontend/control_flow_graph.h" namespace Shader::Gcn { @@ -67,6 +68,39 @@ static bool IgnoresExecMask(const GcnInst& inst) { return false; } +static std::optional ResolveSetPcTarget(std::span list, u32 setpc_index, + std::span pc_map) { + if (setpc_index < 3) { + return std::nullopt; + } + + const auto& getpc = list[setpc_index - 3]; + const auto& arith = list[setpc_index - 2]; + const auto& setpc = list[setpc_index]; + + if (getpc.opcode != Opcode::S_GETPC_B64 || + !(arith.opcode == Opcode::S_ADD_U32 || arith.opcode == Opcode::S_SUB_U32) || + setpc.opcode != Opcode::S_SETPC_B64) + return std::nullopt; + + if (getpc.dst[0].code != setpc.src[0].code || arith.dst[0].code != setpc.src[0].code) + return std::nullopt; + + if (arith.src_count < 2 || arith.src[1].field != OperandField::LiteralConst) + return std::nullopt; + + const u32 imm = arith.src[1].code; + + const s32 signed_offset = + (arith.opcode == Opcode::S_ADD_U32) ? static_cast(imm) : -static_cast(imm); + + const u32 base_pc = pc_map[setpc_index - 3] + getpc.length; + + const u32 result_pc = static_cast(static_cast(base_pc) + signed_offset); + LOG_DEBUG(Render_Recompiler, "SetPC target: {} + {} = {}", base_pc, signed_offset, result_pc); + return result_pc & ~0x3u; +} + static constexpr size_t LabelReserveSize = 32; CFG::CFG(Common::ObjectPool& block_pool_, std::span inst_list_) @@ -89,9 +123,20 @@ void CFG::EmitLabels() { index_to_pc[i] = pc; const GcnInst inst = inst_list[i]; if (inst.IsUnconditionalBranch()) { - const u32 target = inst.BranchTarget(pc); + u32 target = inst.BranchTarget(pc); + if (inst.opcode == Opcode::S_SETPC_B64) { + if (auto t = ResolveSetPcTarget(inst_list, i, index_to_pc)) { + target = *t; + } else { + ASSERT_MSG( + false, + "S_SETPC_B64 without a resolvable offset at PC {:#x} (Index {}): Involved " + "instructions not recognized or invalid pattern", + pc, i); + } + } AddLabel(target); - // Emit this label so that the block ends with s_branch instruction + // Emit this label so that the block ends with the branching instruction AddLabel(pc + inst.length); } else if (inst.IsConditionalBranch()) { const u32 true_label = inst.BranchTarget(pc); @@ -102,6 +147,7 @@ void CFG::EmitLabels() { const u32 next_label = pc + inst.length; AddLabel(next_label); } + pc += inst.length; } index_to_pc[inst_list.size()] = pc; @@ -280,7 +326,18 @@ void CFG::LinkBlocks() { // Find the branch targets from the instruction and link the blocks. // Note: Block end address is one instruction after end_inst. const u32 branch_pc = block.end - end_inst.length; - const u32 target_pc = end_inst.BranchTarget(branch_pc); + u32 target_pc = 0; + if (end_inst.opcode == Opcode::S_SETPC_B64) { + auto tgt = ResolveSetPcTarget(inst_list, block.end_index, index_to_pc); + ASSERT_MSG(tgt, + "S_SETPC_B64 without a resolvable offset at PC {:#x} (Index {}): Involved " + "instructions not recognized or invalid pattern", + branch_pc, block.end_index); + target_pc = *tgt; + } else { + target_pc = end_inst.BranchTarget(branch_pc); + } + if (end_inst.IsUnconditionalBranch()) { auto* target_block = get_block(target_pc); ++target_block->num_predecessors; diff --git a/src/shader_recompiler/frontend/instruction.cpp b/src/shader_recompiler/frontend/instruction.cpp index a0c132053..246c2b85a 100644 --- a/src/shader_recompiler/frontend/instruction.cpp +++ b/src/shader_recompiler/frontend/instruction.cpp @@ -18,7 +18,7 @@ bool GcnInst::IsTerminateInstruction() const { } bool GcnInst::IsUnconditionalBranch() const { - return opcode == Opcode::S_BRANCH; + return opcode == Opcode::S_BRANCH || opcode == Opcode::S_SETPC_B64; } bool GcnInst::IsFork() const { diff --git a/src/shader_recompiler/frontend/translate/scalar_flow.cpp b/src/shader_recompiler/frontend/translate/scalar_flow.cpp index 0e02b77a2..cd1cf51f0 100644 --- a/src/shader_recompiler/frontend/translate/scalar_flow.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_flow.cpp @@ -18,6 +18,7 @@ void Translator::EmitFlowControl(u32 pc, const GcnInst& inst) { return; case Opcode::S_GETPC_B64: return S_GETPC_B64(pc, inst); + case Opcode::S_SETPC_B64: case Opcode::S_WAITCNT: case Opcode::S_NOP: case Opcode::S_ENDPGM: From cda421434bb8d040f47cfc73bafa731afba39aee Mon Sep 17 00:00:00 2001 From: Dmugetsu <168934208+diegolix29@users.noreply.github.com> Date: Tue, 22 Apr 2025 13:49:29 -0600 Subject: [PATCH 25/41] Adding missmatch info to Texture cache assert (#2828) --- src/video_core/texture_cache/texture_cache.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index d41ee57cc..545152ec8 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -326,9 +326,13 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) { info.pixel_format != cache_image.info.pixel_format) { continue; } - ASSERT((cache_image.info.type == info.type || info.size == Extent3D{1, 1, 1} || - True(flags & FindFlags::RelaxFmt))); - image_id = cache_id; + if (!(cache_image.info.type == info.type || info.size == Extent3D{1, 1, 1} || + static_cast(flags & FindFlags::RelaxFmt))) { + ASSERT_MSG(false, "Image cache type mismatch: cache={}, info={}", + int(cache_image.info.type), int(info.type)); + image_id = cache_id; + break; + } } if (True(flags & FindFlags::NoCreate) && !image_id) { From 5b0205bc59f5057203a860f991fef3cb54dc8ed0 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 22 Apr 2025 14:00:08 -0700 Subject: [PATCH 26/41] fix: Texture cache image type assert. --- src/video_core/texture_cache/texture_cache.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 545152ec8..7023dda55 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -326,13 +326,11 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) { info.pixel_format != cache_image.info.pixel_format) { continue; } - if (!(cache_image.info.type == info.type || info.size == Extent3D{1, 1, 1} || - static_cast(flags & FindFlags::RelaxFmt))) { - ASSERT_MSG(false, "Image cache type mismatch: cache={}, info={}", - int(cache_image.info.type), int(info.type)); - image_id = cache_id; - break; - } + ASSERT_MSG((cache_image.info.type == info.type || info.size == Extent3D{1, 1, 1} || + True(flags & FindFlags::RelaxFmt)), + "Image cache type mismatch: cache={}, info={}", + vk::to_string(cache_image.info.type), vk::to_string(info.type)); + image_id = cache_id; } if (True(flags & FindFlags::NoCreate) && !image_id) { From 0297aee3f4871704da9eef42f81ecf5ead8e7a3b Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 22 Apr 2025 15:03:43 -0700 Subject: [PATCH 27/41] texture_cache: Relax mismatched image type from assert to cache miss. (#2830) --- src/video_core/texture_cache/texture_cache.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index 7023dda55..047bb3dfe 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -319,17 +319,14 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) { continue; } if (False(flags & FindFlags::RelaxFmt) && - !IsVulkanFormatCompatible(info.pixel_format, cache_image.info.pixel_format)) { + (!IsVulkanFormatCompatible(info.pixel_format, cache_image.info.pixel_format) || + (cache_image.info.type != info.type && info.size != Extent3D{1, 1, 1}))) { continue; } if (True(flags & FindFlags::ExactFmt) && info.pixel_format != cache_image.info.pixel_format) { continue; } - ASSERT_MSG((cache_image.info.type == info.type || info.size == Extent3D{1, 1, 1} || - True(flags & FindFlags::RelaxFmt)), - "Image cache type mismatch: cache={}, info={}", - vk::to_string(cache_image.info.type), vk::to_string(info.type)); image_id = cache_id; } From 96bee58d0f048c44bbbf76a2fa1434c469df753e Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 22 Apr 2025 21:41:20 -0700 Subject: [PATCH 28/41] ci: Fix macOS SDL build. (#2831) --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 86ca81c38..9393380e2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -206,11 +206,11 @@ jobs: mkdir upload mv ${{github.workspace}}/build/shadps4 upload cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload - tar cf shadps4-macos-sdl.tar.gz -C upload . + install_name_tool -add_rpath "@executable_path" upload/shadps4 - uses: actions/upload-artifact@v4 with: name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} - path: shadps4-macos-sdl.tar.gz + path: upload/ macos-qt: runs-on: macos-15 From b1ebb2fec56c25dc304d74618e2aca04671eddb1 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 22 Apr 2025 22:05:32 -0700 Subject: [PATCH 29/41] fix: Only change macOS working directory for app bundle. --- src/common/path_util.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 702d0fabc..2ff1ddaf7 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -60,7 +60,7 @@ static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) { return nullptr; } -static std::filesystem::path GetBundleParentDirectory() { +static std::optional GetBundleParentDirectory() { if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) { if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) { SCOPE_EXIT { @@ -83,14 +83,16 @@ static std::filesystem::path GetBundleParentDirectory() { } } } - return std::filesystem::current_path(); + return std::nullopt; } #endif static auto UserPaths = [] { #ifdef __APPLE__ // Set the current path to the directory containing the app bundle. - std::filesystem::current_path(GetBundleParentDirectory()); + if (const auto bundle_dir = GetBundleParentDirectory()) { + std::filesystem::current_path(*bundle_dir); + } #endif // Try the portable user directory first. From ee7fe305c9cb69ad3c33b1d2bb0d5b2fa918e982 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Tue, 22 Apr 2025 23:18:39 -0700 Subject: [PATCH 30/41] fix: Make sure right MoltenVK is loaded for macOS SDL. --- src/video_core/renderer_vulkan/vk_platform.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index e656369b2..6e9d825a3 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -223,6 +223,7 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e LOG_INFO(Render_Vulkan, "Creating vulkan instance"); #ifdef __APPLE__ +#ifdef ENABLE_QT_GUI // If the Vulkan loader exists in /usr/local/lib, give it priority. The Vulkan SDK // installs it here by default but it is not in the default library search path. // The loader has a clause to check for it, but at a lower priority than the bundled @@ -231,6 +232,10 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e static vk::detail::DynamicLoader dl = std::filesystem::exists(usr_local_path) ? vk::detail::DynamicLoader(usr_local_path) : vk::detail::DynamicLoader(); +#else + // TODO: Support layer loading in SDL build. For now just make sure we load the right MoltenVK. + static vk::detail::DynamicLoader dl("libMoltenVK.dylib"); +#endif #else static vk::detail::DynamicLoader dl; #endif From 53ca64f6ffba393cef12b6d794ba32570a610bf0 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 23 Apr 2025 01:10:03 -0700 Subject: [PATCH 31/41] renderer_vulkan: Support loading Vulkan layers on macOS SDL build. (#2832) --- .github/workflows/build.yml | 4 +- .gitmodules | 2 +- CMakeLists.txt | 61 +++++++++++-------- externals/MoltenVK/MoltenVK | 2 +- externals/MoltenVK/MoltenVK_icd.json | 8 --- externals/MoltenVK/SPIRV-Cross | 2 +- src/common/path_util.cpp | 2 +- .../renderer_vulkan/vk_platform.cpp | 22 +++++-- 8 files changed, 58 insertions(+), 45 deletions(-) delete mode 100644 externals/MoltenVK/MoltenVK_icd.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9393380e2..55549ab4c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -205,8 +205,8 @@ jobs: run: | mkdir upload mv ${{github.workspace}}/build/shadps4 upload - cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload - install_name_tool -add_rpath "@executable_path" upload/shadps4 + mv ${{github.workspace}}/build/MoltenVK_icd.json upload + mv ${{github.workspace}}/build/libMoltenVK.dylib upload - uses: actions/upload-artifact@v4 with: name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} diff --git a/.gitmodules b/.gitmodules index 9daefe305..065a4570f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,7 +97,7 @@ shallow = true [submodule "externals/MoltenVK/SPIRV-Cross"] path = externals/MoltenVK/SPIRV-Cross - url = https://github.com/billhollings/SPIRV-Cross + url = https://github.com/KhronosGroup/SPIRV-Cross shallow = true [submodule "externals/MoltenVK/MoltenVK"] path = externals/MoltenVK/MoltenVK diff --git a/CMakeLists.txt b/CMakeLists.txt index beea8a1e0..c48d00046 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1083,34 +1083,45 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD) endif() if (APPLE) - if (ENABLE_QT_GUI) - # Include MoltenVK in the app bundle, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers. - set(MVK_ICD ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK_icd.json) - target_sources(shadps4 PRIVATE ${MVK_ICD}) - set_source_files_properties(${MVK_ICD} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d) + # Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers. + set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) - set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) - set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib) - add_custom_command( - OUTPUT ${MVK_DYLIB_DST} - DEPENDS ${MVK_DYLIB_SRC} - COMMAND cmake -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) - add_custom_target(CopyMoltenVK DEPENDS ${MVK_DYLIB_DST}) - add_dependencies(CopyMoltenVK MoltenVK) - add_dependencies(shadps4 CopyMoltenVK) - set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks") - else() - # For non-bundled SDL build, just do a normal library link. - target_link_libraries(shadps4 PRIVATE MoltenVK) - endif() + if (ENABLE_QT_GUI) + set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks") + set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json) + set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib) + set(MVK_DYLIB_ICD_PATH "../../../Frameworks/libMoltenVK.dylib") + else() + set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path") + set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/MoltenVK_icd.json) + set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/libMoltenVK.dylib) + set(MVK_DYLIB_ICD_PATH "./libMoltenVK.dylib") + endif() - if (ARCHITECTURE STREQUAL "x86_64") - # Reserve system-managed memory space. - target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000) - endif() + cmake_path(GET MVK_ICD_DST PARENT_PATH MVK_ICD_DST_PARENT) + cmake_path(GET MVK_DYLIB_DST PARENT_PATH MVK_DYLIB_DST_PARENT) - # Replacement for std::chrono::time_zone - target_link_libraries(shadps4 PRIVATE date::date-tz) + set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.2.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}") + add_custom_command( + OUTPUT ${MVK_ICD_DST} + COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_ICD_DST_PARENT} && ${CMAKE_COMMAND} -E echo ${MVK_ICD} > ${MVK_ICD_DST}) + + add_custom_command( + OUTPUT ${MVK_DYLIB_DST} + DEPENDS ${MVK_DYLIB_SRC} + COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DYLIB_DST_PARENT} && ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) + + add_custom_target(CopyMoltenVK DEPENDS ${MVK_ICD_DST} ${MVK_DYLIB_DST}) + add_dependencies(CopyMoltenVK MoltenVK) + add_dependencies(shadps4 CopyMoltenVK) + + if (ARCHITECTURE STREQUAL "x86_64") + # Reserve system-managed memory space. + target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000) + endif() + + # Replacement for std::chrono::time_zone + target_link_libraries(shadps4 PRIVATE date::date-tz) endif() if (NOT ENABLE_QT_GUI) diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 067fc6c85..4cf8f9468 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 067fc6c85b02f37dfda58eeda49d8458e093ed60 +Subproject commit 4cf8f94684c53e581eb9cc694dd3305d1f7d9959 diff --git a/externals/MoltenVK/MoltenVK_icd.json b/externals/MoltenVK/MoltenVK_icd.json deleted file mode 100644 index 2c3319263..000000000 --- a/externals/MoltenVK/MoltenVK_icd.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "file_format_version": "1.0.0", - "ICD": { - "library_path": "../../../Frameworks/libMoltenVK.dylib", - "api_version": "1.2.0", - "is_portability_driver": true - } -} diff --git a/externals/MoltenVK/SPIRV-Cross b/externals/MoltenVK/SPIRV-Cross index 185833a61..2275d0efc 160000 --- a/externals/MoltenVK/SPIRV-Cross +++ b/externals/MoltenVK/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 185833a61cbe29ce3bfb5a499ffb3dfeaee3bbe7 +Subproject commit 2275d0efc4f2fa46851035d9d3c67c105bc8b99e diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 2ff1ddaf7..1a6ff9ec8 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -88,7 +88,7 @@ static std::optional GetBundleParentDirectory() { #endif static auto UserPaths = [] { -#ifdef __APPLE__ +#if defined(__APPLE__) && defined(ENABLE_QT_GUI) // Set the current path to the directory containing the app bundle. if (const auto bundle_dir = GetBundleParentDirectory()) { std::filesystem::current_path(*bundle_dir); diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index 6e9d825a3..c49e62f4e 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -22,6 +22,10 @@ #include "sdl_window.h" #include "video_core/renderer_vulkan/vk_platform.h" +#ifdef __APPLE__ +#include +#endif + namespace Vulkan { static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation"; @@ -223,19 +227,25 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e LOG_INFO(Render_Vulkan, "Creating vulkan instance"); #ifdef __APPLE__ -#ifdef ENABLE_QT_GUI +#ifndef ENABLE_QT_GUI + // Initialize the environment with the path to the MoltenVK ICD, so that the loader will + // find it. + static const auto icd_path = [] { + char path[PATH_MAX]; + u32 length = PATH_MAX; + _NSGetExecutablePath(path, &length); + return std::filesystem::path(path).parent_path() / "MoltenVK_icd.json"; + }(); + setenv("VK_DRIVER_FILES", icd_path.c_str(), true); +#endif // If the Vulkan loader exists in /usr/local/lib, give it priority. The Vulkan SDK - // installs it here by default but it is not in the default library search path. + // installs it here by default, but it is not in the default library search path. // The loader has a clause to check for it, but at a lower priority than the bundled // libMoltenVK.dylib, so we need to handle it ourselves to give it priority. static const std::string usr_local_path = "/usr/local/lib/libvulkan.dylib"; static vk::detail::DynamicLoader dl = std::filesystem::exists(usr_local_path) ? vk::detail::DynamicLoader(usr_local_path) : vk::detail::DynamicLoader(); -#else - // TODO: Support layer loading in SDL build. For now just make sure we load the right MoltenVK. - static vk::detail::DynamicLoader dl("libMoltenVK.dylib"); -#endif #else static vk::detail::DynamicLoader dl; #endif From 354a2e6946319e8c6855146829659efa107ab32f Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 23 Apr 2025 13:05:36 +0300 Subject: [PATCH 32/41] tagged v0.8.0 release --- CMakeLists.txt | 8 ++++---- dist/net.shadps4.shadPS4.metainfo.xml | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c48d00046..e91939949 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,13 +202,13 @@ execute_process( # Set Version set(EMULATOR_VERSION_MAJOR "0") -set(EMULATOR_VERSION_MINOR "7") -set(EMULATOR_VERSION_PATCH "1") +set(EMULATOR_VERSION_MINOR "8") +set(EMULATOR_VERSION_PATCH "0") set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}") -set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP") -set(APP_IS_RELEASE false) +set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}") +set(APP_IS_RELEASE true) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY) message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}") diff --git a/dist/net.shadps4.shadPS4.metainfo.xml b/dist/net.shadps4.shadPS4.metainfo.xml index 99f9e070d..9f7b4f9c5 100644 --- a/dist/net.shadps4.shadPS4.metainfo.xml +++ b/dist/net.shadps4.shadPS4.metainfo.xml @@ -37,6 +37,9 @@ Game + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.8.0 + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.7.0 From 5db162cbcd7ba73a93576566dabb84de3ac48293 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Wed, 23 Apr 2025 13:24:57 +0300 Subject: [PATCH 33/41] started 0.8.1 WIP --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e91939949..967229d6a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,12 +203,12 @@ execute_process( # Set Version set(EMULATOR_VERSION_MAJOR "0") set(EMULATOR_VERSION_MINOR "8") -set(EMULATOR_VERSION_PATCH "0") +set(EMULATOR_VERSION_PATCH "1") set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}") -set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH}") -set(APP_IS_RELEASE true) +set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_VERSION_PATCH} WIP") +set(APP_IS_RELEASE false) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY) message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}") From aeee7706eeb6afd82ea00bc152c2665c5113c84f Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 23 Apr 2025 03:28:31 -0700 Subject: [PATCH 34/41] renderer_vulkan: Restore Vulkan version to 1.3 (#2827) Co-authored-by: georgemoralis --- .../backend/spirv/emit_spirv.cpp | 3 +- .../renderer_vulkan/host_passes/pp_pass.cpp | 2 +- .../renderer_vulkan/vk_graphics_pipeline.cpp | 24 ++++---- .../renderer_vulkan/vk_instance.cpp | 55 ++++++------------- .../renderer_vulkan/vk_pipeline_cache.cpp | 4 +- src/video_core/renderer_vulkan/vk_platform.h | 2 +- .../renderer_vulkan/vk_scheduler.cpp | 40 +++++++------- 7 files changed, 55 insertions(+), 75 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 036df24d8..936f82cd6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -335,8 +335,7 @@ void DefineEntryPoint(const Info& info, EmitContext& ctx, Id main) { ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft); } if (info.has_discard) { - ctx.AddExtension("SPV_EXT_demote_to_helper_invocation"); - ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); + ctx.AddCapability(spv::Capability::DemoteToHelperInvocation); } if (info.stores.GetAny(IR::Attribute::Depth)) { ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); diff --git a/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp b/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp index c854e124f..0c40ffd7a 100644 --- a/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp +++ b/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp @@ -78,7 +78,7 @@ void PostProcessingPass::Create(vk::Device device) { const std::array pp_color_formats{ vk::Format::eB8G8R8A8Unorm, // swapchain.GetSurfaceFormat().format, }; - const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci{ + const vk::PipelineRenderingCreateInfo pipeline_rendering_ci{ .colorAttachmentCount = pp_color_formats.size(), .pColorAttachmentFormats = pp_color_formats.data(), }; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 354e22331..7c020a012 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -122,21 +122,21 @@ GraphicsPipeline::GraphicsPipeline( }; boost::container::static_vector dynamic_states = { - vk::DynamicState::eViewportWithCountEXT, vk::DynamicState::eScissorWithCountEXT, - vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT, - vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT, - vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias, - vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference, - vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask, - vk::DynamicState::eStencilOpEXT, vk::DynamicState::eCullModeEXT, - vk::DynamicState::eFrontFaceEXT, + vk::DynamicState::eViewportWithCount, vk::DynamicState::eScissorWithCount, + vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnable, + vk::DynamicState::eDepthWriteEnable, vk::DynamicState::eDepthCompareOp, + vk::DynamicState::eDepthBiasEnable, vk::DynamicState::eDepthBias, + vk::DynamicState::eStencilTestEnable, vk::DynamicState::eStencilReference, + vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask, + vk::DynamicState::eStencilOp, vk::DynamicState::eCullMode, + vk::DynamicState::eFrontFace, }; if (instance.IsPrimitiveRestartDisableSupported()) { - dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnableEXT); + dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnable); } if (instance.IsDepthBoundsSupported()) { - dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT); + dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnable); dynamic_states.push_back(vk::DynamicState::eDepthBounds); } if (instance.IsDynamicColorWriteMaskSupported()) { @@ -145,7 +145,7 @@ GraphicsPipeline::GraphicsPipeline( if (instance.IsVertexInputDynamicState()) { dynamic_states.push_back(vk::DynamicState::eVertexInputEXT); } else if (!vertex_bindings.empty()) { - dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT); + dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStride); } const vk::PipelineDynamicStateCreateInfo dynamic_info = { @@ -212,7 +212,7 @@ GraphicsPipeline::GraphicsPipeline( }); } - const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci = { + const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = { .colorAttachmentCount = key.num_color_attachments, .pColorAttachmentFormats = key.color_formats.data(), .depthAttachmentFormat = key.depth_format, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 0df020116..089c0f00d 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -203,12 +203,14 @@ std::string Instance::GetDriverVersionName() { } bool Instance::CreateDevice() { - const vk::StructureChain feature_chain = physical_device.getFeatures2< - vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features, - vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceRobustness2FeaturesEXT, - vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT, - vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT, - vk::PhysicalDevicePortabilitySubsetFeaturesKHR>(); + const vk::StructureChain feature_chain = + physical_device + .getFeatures2(); features = feature_chain.get().features; const vk::StructureChain properties_chain = physical_device.getProperties2< @@ -240,18 +242,6 @@ bool Instance::CreateDevice() { return false; }; - // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 - // with extensions. - ASSERT(add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)); - ASSERT(add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME) || - driver_id == vk::DriverId::eIntelProprietaryWindows); - ASSERT(add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME)); - // Required ASSERT(add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)); ASSERT(add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)); @@ -324,6 +314,7 @@ bool Instance::CreateDevice() { feature_chain.get(); const auto vk11_features = feature_chain.get(); const auto vk12_features = feature_chain.get(); + const auto vk13_features = feature_chain.get(); vk::StructureChain device_chain = { vk::DeviceCreateInfo{ .queueCreateInfoCount = 1u, @@ -372,26 +363,14 @@ bool Instance::CreateDevice() { .hostQueryReset = vk12_features.hostQueryReset, .timelineSemaphore = vk12_features.timelineSemaphore, }, - // Vulkan 1.3 promoted extensions - vk::PhysicalDeviceDynamicRenderingFeaturesKHR{ - .dynamicRendering = true, + vk::PhysicalDeviceVulkan13Features{ + .robustImageAccess = vk13_features.robustImageAccess, + .shaderDemoteToHelperInvocation = vk13_features.shaderDemoteToHelperInvocation, + .synchronization2 = vk13_features.synchronization2, + .dynamicRendering = vk13_features.dynamicRendering, + .maintenance4 = vk13_features.maintenance4, }, - vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT{ - .shaderDemoteToHelperInvocation = true, - }, - vk::PhysicalDeviceSynchronization2Features{ - .synchronization2 = true, - }, - vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{ - .extendedDynamicState = true, - }, - vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT{ - .extendedDynamicState2 = true, - }, - vk::PhysicalDeviceMaintenance4FeaturesKHR{ - .maintenance4 = true, - }, - // Other extensions + // Extensions vk::PhysicalDeviceCustomBorderColorFeaturesEXT{ .customBorderColors = true, .customBorderColorWithoutFormat = true, @@ -547,7 +526,7 @@ void Instance::CollectToolingInfo() { // Currently causes issues with Reshade on AMD proprietary, disabled until fix released. return; } - const auto [tools_result, tools] = physical_device.getToolPropertiesEXT(); + const auto [tools_result, tools] = physical_device.getToolProperties(); if (tools_result != vk::Result::eSuccess) { LOG_ERROR(Render_Vulkan, "Could not get Vulkan tool properties: {}", vk::to_string(tools_result)); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index bad2a549c..efb1966ba 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -26,6 +26,8 @@ using Shader::LogicalStage; using Shader::Stage; using Shader::VsOutput; +constexpr static auto SpirvVersion1_6 = 0x00010600U; + constexpr static std::array DescriptorHeapSizes = { vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 8192}, vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer, 1024}, @@ -192,7 +194,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, desc_heap{instance, scheduler.GetMasterSemaphore(), DescriptorHeapSizes} { const auto& vk12_props = instance.GetVk12Properties(); profile = Shader::Profile{ - .supported_spirv = instance.ApiVersion() >= VK_API_VERSION_1_3 ? 0x00010600U : 0x00010500U, + .supported_spirv = SpirvVersion1_6, .subgroup_size = instance.SubgroupSize(), .support_fp32_denorm_preserve = bool(vk12_props.shaderDenormPreserveFloat32), .support_fp32_denorm_flush = bool(vk12_props.shaderDenormFlushToZeroFloat32), diff --git a/src/video_core/renderer_vulkan/vk_platform.h b/src/video_core/renderer_vulkan/vk_platform.h index 6a6ebeb15..b8f5f9f11 100644 --- a/src/video_core/renderer_vulkan/vk_platform.h +++ b/src/video_core/renderer_vulkan/vk_platform.h @@ -18,7 +18,7 @@ class WindowSDL; namespace Vulkan { -constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_2; +constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_3; vk::SurfaceKHR CreateSurface(vk::Instance instance, const Frontend::WindowSDL& emu_window); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index a48d93dee..8d4188a22 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -170,29 +170,29 @@ void Scheduler::SubmitExecution(SubmitInfo& info) { void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf) { if (dirty_state.viewports) { dirty_state.viewports = false; - cmdbuf.setViewportWithCountEXT(viewports); + cmdbuf.setViewportWithCount(viewports); } if (dirty_state.scissors) { dirty_state.scissors = false; - cmdbuf.setScissorWithCountEXT(scissors); + cmdbuf.setScissorWithCount(scissors); } if (dirty_state.depth_test_enabled) { dirty_state.depth_test_enabled = false; - cmdbuf.setDepthTestEnableEXT(depth_test_enabled); + cmdbuf.setDepthTestEnable(depth_test_enabled); } if (dirty_state.depth_write_enabled) { dirty_state.depth_write_enabled = false; // Note that this must be set in a command buffer even if depth test is disabled. - cmdbuf.setDepthWriteEnableEXT(depth_write_enabled); + cmdbuf.setDepthWriteEnable(depth_write_enabled); } if (depth_test_enabled && dirty_state.depth_compare_op) { dirty_state.depth_compare_op = false; - cmdbuf.setDepthCompareOpEXT(depth_compare_op); + cmdbuf.setDepthCompareOp(depth_compare_op); } if (dirty_state.depth_bounds_test_enabled) { dirty_state.depth_bounds_test_enabled = false; if (instance.IsDepthBoundsSupported()) { - cmdbuf.setDepthBoundsTestEnableEXT(depth_bounds_test_enabled); + cmdbuf.setDepthBoundsTestEnable(depth_bounds_test_enabled); } } if (depth_bounds_test_enabled && dirty_state.depth_bounds) { @@ -203,7 +203,7 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd } if (dirty_state.depth_bias_enabled) { dirty_state.depth_bias_enabled = false; - cmdbuf.setDepthBiasEnableEXT(depth_bias_enabled); + cmdbuf.setDepthBiasEnable(depth_bias_enabled); } if (depth_bias_enabled && dirty_state.depth_bias) { dirty_state.depth_bias = false; @@ -211,28 +211,28 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd } if (dirty_state.stencil_test_enabled) { dirty_state.stencil_test_enabled = false; - cmdbuf.setStencilTestEnableEXT(stencil_test_enabled); + cmdbuf.setStencilTestEnable(stencil_test_enabled); } if (stencil_test_enabled) { if (dirty_state.stencil_front_ops && dirty_state.stencil_back_ops && stencil_front_ops == stencil_back_ops) { dirty_state.stencil_front_ops = false; dirty_state.stencil_back_ops = false; - cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack, - stencil_front_ops.fail_op, stencil_front_ops.pass_op, - stencil_front_ops.depth_fail_op, stencil_front_ops.compare_op); + cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eFrontAndBack, stencil_front_ops.fail_op, + stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op, + stencil_front_ops.compare_op); } else { if (dirty_state.stencil_front_ops) { dirty_state.stencil_front_ops = false; - cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, stencil_front_ops.fail_op, - stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op, - stencil_front_ops.compare_op); + cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eFront, stencil_front_ops.fail_op, + stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op, + stencil_front_ops.compare_op); } if (dirty_state.stencil_back_ops) { dirty_state.stencil_back_ops = false; - cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, stencil_back_ops.fail_op, - stencil_back_ops.pass_op, stencil_back_ops.depth_fail_op, - stencil_back_ops.compare_op); + cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eBack, stencil_back_ops.fail_op, + stencil_back_ops.pass_op, stencil_back_ops.depth_fail_op, + stencil_back_ops.compare_op); } } if (dirty_state.stencil_front_reference && dirty_state.stencil_back_reference && @@ -291,16 +291,16 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd if (dirty_state.primitive_restart_enable) { dirty_state.primitive_restart_enable = false; if (instance.IsPrimitiveRestartDisableSupported()) { - cmdbuf.setPrimitiveRestartEnableEXT(primitive_restart_enable); + cmdbuf.setPrimitiveRestartEnable(primitive_restart_enable); } } if (dirty_state.cull_mode) { dirty_state.cull_mode = false; - cmdbuf.setCullModeEXT(cull_mode); + cmdbuf.setCullMode(cull_mode); } if (dirty_state.front_face) { dirty_state.front_face = false; - cmdbuf.setFrontFaceEXT(front_face); + cmdbuf.setFrontFace(front_face); } if (dirty_state.blend_constants) { dirty_state.blend_constants = false; From 3f4249084cfc3b94db7d8241647ff496f49d4b90 Mon Sep 17 00:00:00 2001 From: tlarok <116431383+tlarok@users.noreply.github.com> Date: Wed, 23 Apr 2025 12:41:14 +0200 Subject: [PATCH 35/41] multikey for kbm_gui (#2778) * Update kbm_gui.cpp * Update kbm_gui.cpp * Update kbm_gui.h * Update kbm_gui.cpp * lunix test * linux test * Update kbm_gui.h * Update kbm_gui.cpp * Update kbm_gui.cpp * Update kbm_gui.cpp * Update kbm_gui.cpp * Update kbm_gui.h * Update kbm_gui.cpp * Update kbm_gui.h * Update kbm_gui.cpp * Update kbm_gui.h * Update kbm_gui.cpp * kbm_gui.cpp's names fix just cleaning my code * name fix * Update kbm_gui.cpp * Update kbm_gui.h * Update kbm_gui.cpp * Update src/qt_gui/kbm_gui.cpp Co-authored-by: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> * clean up from main * bruh, welp here we go again --------- Co-authored-by: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> --- src/qt_gui/kbm_gui.cpp | 273 +++++++++++++++++++++++------------------ src/qt_gui/kbm_gui.h | 17 +++ 2 files changed, 169 insertions(+), 121 deletions(-) diff --git a/src/qt_gui/kbm_gui.cpp b/src/qt_gui/kbm_gui.cpp index 2e1f6ddce..15e9008ab 100644 --- a/src/qt_gui/kbm_gui.cpp +++ b/src/qt_gui/kbm_gui.cpp @@ -608,21 +608,28 @@ void KBMSettings::CheckMapping(QPushButton*& button) { MappingTimer -= 1; button->setText(tr("Press a key") + " [" + QString::number(MappingTimer) + "]"); + if (pressedKeys.size() > 0) { + QStringList keyStrings; + + for (const QString& buttonAction : pressedKeys) { + keyStrings << buttonAction; + } + + QString combo = keyStrings.join(","); + SetMapping(combo); + MappingCompleted = true; + EnableMapping = false; + + MappingButton->setText(combo); + pressedKeys.clear(); + timer->stop(); + } if (MappingCompleted) { EnableMapping = false; EnableMappingButtons(); timer->stop(); - if (mapping == "lshift" || mapping == "lalt" || mapping == "lctrl" || mapping == "lmeta" || - mapping == "lwin") { - modifier = ""; - } - - if (modifier != "") { - button->setText(modifier + ", " + mapping); - } else { - button->setText(mapping); - } + button->setText(mapping); } if (MappingTimer <= 0) { @@ -647,322 +654,346 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) { } if (EnableMapping) { - if (Qt::ShiftModifier & QApplication::keyboardModifiers()) { - modifier = "lshift"; - } else if (Qt::AltModifier & QApplication::keyboardModifiers()) { - modifier = "lalt"; - } else if (Qt::ControlModifier & QApplication::keyboardModifiers()) { - modifier = "lctrl"; - } else if (Qt::MetaModifier & QApplication::keyboardModifiers()) { -#ifdef _WIN32 - modifier = "lwin"; -#else - modifier = "lmeta"; -#endif - } - if (event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(event); + if (keyEvent->isAutoRepeat()) + return true; + + if (pressedKeys.size() >= 3) { + return true; + } + switch (keyEvent->key()) { case Qt::Key_Space: - SetMapping("space"); + pressedKeys.insert("space"); break; case Qt::Key_Comma: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpcomma"); + pressedKeys.insert("kpcomma"); } else { - SetMapping("comma"); + pressedKeys.insert("comma"); } break; case Qt::Key_Period: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpperiod"); + pressedKeys.insert("kpperiod"); } else { - SetMapping("period"); + pressedKeys.insert("period"); } break; case Qt::Key_Slash: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) - SetMapping("kpdivide"); + pressedKeys.insert("kpdivide"); break; case Qt::Key_Asterisk: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) - SetMapping("kpmultiply"); + pressedKeys.insert("kpmultiply"); break; case Qt::Key_Question: - SetMapping("question"); + pressedKeys.insert("question"); break; case Qt::Key_Semicolon: - SetMapping("semicolon"); + pressedKeys.insert("semicolon"); break; case Qt::Key_Minus: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpminus"); + pressedKeys.insert("kpminus"); } else { - SetMapping("minus"); + pressedKeys.insert("minus"); } break; case Qt::Key_Plus: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpplus"); + pressedKeys.insert("kpplus"); } else { - SetMapping("plus"); + pressedKeys.insert("plus"); } break; case Qt::Key_ParenLeft: - SetMapping("lparenthesis"); + pressedKeys.insert("lparenthesis"); break; case Qt::Key_ParenRight: - SetMapping("rparenthesis"); + pressedKeys.insert("rparenthesis"); break; case Qt::Key_BracketLeft: - SetMapping("lbracket"); + pressedKeys.insert("lbracket"); break; case Qt::Key_BracketRight: - SetMapping("rbracket"); + pressedKeys.insert("rbracket"); break; case Qt::Key_BraceLeft: - SetMapping("lbrace"); + pressedKeys.insert("lbrace"); break; case Qt::Key_BraceRight: - SetMapping("rbrace"); + pressedKeys.insert("rbrace"); break; case Qt::Key_Backslash: - SetMapping("backslash"); + pressedKeys.insert("backslash"); break; case Qt::Key_Tab: - SetMapping("tab"); + pressedKeys.insert("tab"); break; case Qt::Key_Backspace: - SetMapping("backspace"); + pressedKeys.insert("backspace"); break; case Qt::Key_Return: - SetMapping("enter"); + pressedKeys.insert("enter"); break; case Qt::Key_Enter: - SetMapping("kpenter"); + pressedKeys.insert("kpenter"); + break; + case Qt::Key_Home: + pressedKeys.insert("home"); + break; + case Qt::Key_End: + pressedKeys.insert("end"); + break; + case Qt::Key_PageDown: + pressedKeys.insert("pgdown"); + break; + case Qt::Key_PageUp: + pressedKeys.insert("pgup"); + break; + case Qt::Key_CapsLock: + pressedKeys.insert("capslock"); break; case Qt::Key_Escape: - SetMapping("unmapped"); + pressedKeys.insert("unmapped"); break; case Qt::Key_Shift: - SetMapping("lshift"); + if (keyEvent->nativeScanCode() == rshift) { + pressedKeys.insert("rshift"); + } else { + pressedKeys.insert("lshift"); + } break; case Qt::Key_Alt: - SetMapping("lalt"); + if (keyEvent->nativeScanCode() == ralt) { + pressedKeys.insert("ralt"); + } else { + pressedKeys.insert("lalt"); + } break; case Qt::Key_Control: - SetMapping("lctrl"); + if (keyEvent->nativeScanCode() == rctrl) { + pressedKeys.insert("rctrl"); + } else { + pressedKeys.insert("lctrl"); + } break; case Qt::Key_Meta: activateWindow(); #ifdef _WIN32 - SetMapping("lwin"); + pressedKeys.insert("lwin"); #else - SetMapping("lmeta"); + pressedKeys.insert("lmeta"); #endif case Qt::Key_1: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp1"); + pressedKeys.insert("kp1"); } else { - SetMapping("1"); + pressedKeys.insert("1"); } break; case Qt::Key_2: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp2"); + pressedKeys.insert("kp2"); } else { - SetMapping("2"); + pressedKeys.insert("2"); } break; case Qt::Key_3: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp3"); + pressedKeys.insert("kp3"); } else { - SetMapping("3"); + pressedKeys.insert("3"); } break; case Qt::Key_4: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp4"); + pressedKeys.insert("kp4"); } else { - SetMapping("4"); + pressedKeys.insert("4"); } break; case Qt::Key_5: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp5"); + pressedKeys.insert("kp5"); } else { - SetMapping("5"); + pressedKeys.insert("5"); } break; case Qt::Key_6: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp6"); + pressedKeys.insert("kp6"); } else { - SetMapping("6"); + pressedKeys.insert("6"); } break; case Qt::Key_7: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp7"); + pressedKeys.insert("kp7"); } else { - SetMapping("7"); + pressedKeys.insert("7"); } break; case Qt::Key_8: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp8"); + pressedKeys.insert("kp8"); } else { - SetMapping("8"); + pressedKeys.insert("8"); } break; case Qt::Key_9: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp9"); + pressedKeys.insert("kp9"); } else { - SetMapping("9"); + pressedKeys.insert("9"); } break; case Qt::Key_0: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp0"); + pressedKeys.insert("kp0"); } else { - SetMapping("0"); + pressedKeys.insert("0"); } break; case Qt::Key_Up: activateWindow(); - SetMapping("up"); + pressedKeys.insert("up"); break; case Qt::Key_Down: - SetMapping("down"); + pressedKeys.insert("down"); break; case Qt::Key_Left: - SetMapping("left"); + pressedKeys.insert("left"); break; case Qt::Key_Right: - SetMapping("right"); + pressedKeys.insert("right"); break; case Qt::Key_A: - SetMapping("a"); + pressedKeys.insert("a"); break; case Qt::Key_B: - SetMapping("b"); + pressedKeys.insert("b"); break; case Qt::Key_C: - SetMapping("c"); + pressedKeys.insert("c"); break; case Qt::Key_D: - SetMapping("d"); + pressedKeys.insert("d"); break; case Qt::Key_E: - SetMapping("e"); + pressedKeys.insert("e"); break; case Qt::Key_F: - SetMapping("f"); + pressedKeys.insert("f"); break; case Qt::Key_G: - SetMapping("g"); + pressedKeys.insert("g"); break; case Qt::Key_H: - SetMapping("h"); + pressedKeys.insert("h"); break; case Qt::Key_I: - SetMapping("i"); + pressedKeys.insert("i"); break; case Qt::Key_J: - SetMapping("j"); + pressedKeys.insert("j"); break; case Qt::Key_K: - SetMapping("k"); + pressedKeys.insert("k"); break; case Qt::Key_L: - SetMapping("l"); + pressedKeys.insert("l"); break; case Qt::Key_M: - SetMapping("m"); + pressedKeys.insert("m"); break; case Qt::Key_N: - SetMapping("n"); + pressedKeys.insert("n"); break; case Qt::Key_O: - SetMapping("o"); + pressedKeys.insert("o"); break; case Qt::Key_P: - SetMapping("p"); + pressedKeys.insert("p"); break; case Qt::Key_Q: - SetMapping("q"); + pressedKeys.insert("q"); break; case Qt::Key_R: - SetMapping("r"); + pressedKeys.insert("r"); break; case Qt::Key_S: - SetMapping("s"); + pressedKeys.insert("s"); break; case Qt::Key_T: - SetMapping("t"); + pressedKeys.insert("t"); break; case Qt::Key_U: - SetMapping("u"); + pressedKeys.insert("u"); break; case Qt::Key_V: - SetMapping("v"); + pressedKeys.insert("v"); break; case Qt::Key_W: - SetMapping("w"); + pressedKeys.insert("w"); break; case Qt::Key_X: - SetMapping("x"); + pressedKeys.insert("x"); break; case Qt::Key_Y: - SetMapping("Y"); + pressedKeys.insert("Y"); break; case Qt::Key_Z: - SetMapping("z"); + pressedKeys.insert("z"); break; default: break; } return true; } + } - if (event->type() == QEvent::MouseButtonPress) { - QMouseEvent* mouseEvent = static_cast(event); + if (event->type() == QEvent::MouseButtonPress) { + QMouseEvent* mouseEvent = static_cast(event); + if (pressedKeys.size() < 3) { switch (mouseEvent->button()) { case Qt::LeftButton: - SetMapping("leftbutton"); + pressedKeys.insert("leftbutton"); break; case Qt::RightButton: - SetMapping("rightbutton"); + pressedKeys.insert("rightbutton"); break; case Qt::MiddleButton: - SetMapping("middlebutton"); + pressedKeys.insert("middlebutton"); break; default: break; } return true; } + } - const QList AxisList = { - ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton, - ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton}; + const QList AxisList = { + ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton, + ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton}; - if (event->type() == QEvent::Wheel) { - QWheelEvent* wheelEvent = static_cast(event); + if (event->type() == QEvent::Wheel) { + QWheelEvent* wheelEvent = static_cast(event); + if (pressedKeys.size() < 3) { if (wheelEvent->angleDelta().y() > 5) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { - SetMapping("mousewheelup"); + pressedKeys.insert("mousewheelup"); } else { QMessageBox::information(this, tr("Cannot set mapping"), tr("Mousewheel cannot be mapped to stick outputs")); } } else if (wheelEvent->angleDelta().y() < -5) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { - SetMapping("mousewheeldown"); + pressedKeys.insert("mousewheeldown"); } else { QMessageBox::information(this, tr("Cannot set mapping"), tr("Mousewheel cannot be mapped to stick outputs")); @@ -972,9 +1003,9 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { // QT changes scrolling to horizontal for all widgets with the alt modifier if (Qt::AltModifier & QApplication::keyboardModifiers()) { - SetMapping("mousewheelup"); + pressedKeys.insert("mousewheelup"); } else { - SetMapping("mousewheelright"); + pressedKeys.insert("mousewheelright"); } } else { QMessageBox::information(this, tr("Cannot set mapping"), @@ -983,18 +1014,18 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) { } else if (wheelEvent->angleDelta().x() < -5) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { if (Qt::AltModifier & QApplication::keyboardModifiers()) { - SetMapping("mousewheeldown"); + pressedKeys.insert("mousewheeldown"); } else { - SetMapping("mousewheelleft"); + pressedKeys.insert("mousewheelleft"); } } else { QMessageBox::information(this, tr("Cannot set mapping"), tr("Mousewheel cannot be mapped to stick outputs")); } } - return true; } } + return QDialog::eventFilter(obj, event); } diff --git a/src/qt_gui/kbm_gui.h b/src/qt_gui/kbm_gui.h index 06e58eef6..bfeed2b01 100644 --- a/src/qt_gui/kbm_gui.h +++ b/src/qt_gui/kbm_gui.h @@ -25,6 +25,22 @@ private: std::unique_ptr ui; std::shared_ptr m_game_info; +#ifdef _WIN32 + const int lctrl = 29; + const int rctrl = 57373; + const int lalt = 56; + const int ralt = 57400; + const int lshift = 42; + const int rshift = 54; +#else + const int lctrl = 37; + const int rctrl = 105; + const int lalt = 64; + const int ralt = 108; + const int lshift = 50; + const int rshift = 62; +#endif + bool eventFilter(QObject* obj, QEvent* event) override; void ButtonConnects(); void SetUIValuestoMappings(std::string config_id); @@ -33,6 +49,7 @@ private: void EnableMappingButtons(); void SetMapping(QString input); + QSet pressedKeys; bool EnableMapping = false; bool MappingCompleted = false; bool HelpWindowOpen = false; From 4ecdcf77d13dcac5562676f03638a28c71f272d2 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 23 Apr 2025 09:58:00 -0700 Subject: [PATCH 36/41] build: Update MoltenVK ICD API version. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 967229d6a..3561c2c3a 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1101,7 +1101,7 @@ if (APPLE) cmake_path(GET MVK_ICD_DST PARENT_PATH MVK_ICD_DST_PARENT) cmake_path(GET MVK_DYLIB_DST PARENT_PATH MVK_DYLIB_DST_PARENT) - set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.2.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}") + set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.3.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}") add_custom_command( OUTPUT ${MVK_ICD_DST} COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_ICD_DST_PARENT} && ${CMAKE_COMMAND} -E echo ${MVK_ICD} > ${MVK_ICD_DST}) From ce3aded3e527c92f7a96a32dd5957354e311e225 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 23 Apr 2025 11:09:04 -0700 Subject: [PATCH 37/41] fix: Intel crash on startup. --- src/video_core/renderer_vulkan/vk_instance.cpp | 8 +++++--- src/video_core/renderer_vulkan/vk_instance.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 089c0f00d..d33a1607b 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -521,9 +521,11 @@ void Instance::CollectDeviceParameters() { LOG_INFO(Render_Vulkan, "GPU_Vulkan_Extensions: {}", extensions); } -void Instance::CollectToolingInfo() { - if (GetDriverID() == vk::DriverId::eAmdProprietary) { - // Currently causes issues with Reshade on AMD proprietary, disabled until fix released. +void Instance::CollectToolingInfo() const { + if (driver_id == vk::DriverId::eAmdProprietary || + driver_id == vk::DriverId::eIntelProprietaryWindows) { + // AMD: Causes issues with Reshade. + // Intel: Causes crash on start. return; } const auto [tools_result, tools] = physical_device.getToolProperties(); diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index a9de01f84..b3f3e60b6 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -311,7 +311,7 @@ private: /// Collects telemetry information from the device. void CollectDeviceParameters(); - void CollectToolingInfo(); + void CollectToolingInfo() const; /// Gets the supported feature flags for a format. [[nodiscard]] vk::FormatFeatureFlags2 GetFormatFeatureFlags(vk::Format format) const; From a12d447bd65270cf447532b93263009cedd43970 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Thu, 24 Apr 2025 14:21:14 -0500 Subject: [PATCH 38/41] sceKernelAllocateDirectMemory hotfixes (#2838) * Update memory.cpp * Clean logic FindDmemArea guarantees that the first dmem area we check contains search_start. Any dmem areas beyond the first one will be entirely past search_start, so checking against it in the loop is unnecessary. --- src/core/memory.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index cb80d6be4..494ffa70c 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -142,7 +142,7 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, auto mapping_start = search_start > dmem_area->second.base ? Common::AlignUp(search_start, alignment) : Common::AlignUp(dmem_area->second.base, alignment); - auto mapping_end = Common::AlignUp(mapping_start + size, alignment); + auto mapping_end = mapping_start + size; // Find the first free, large enough dmem area in the range. while ((!dmem_area->second.is_free || dmem_area->second.GetEnd() < mapping_end) && @@ -151,10 +151,8 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, dmem_area++; // Update local variables based on the new dmem_area - mapping_start = search_start > dmem_area->second.base - ? Common::AlignUp(search_start, alignment) - : Common::AlignUp(dmem_area->second.base, alignment); - mapping_end = Common::AlignUp(mapping_start + size, alignment); + mapping_start = Common::AlignUp(dmem_area->second.base, alignment); + mapping_end = mapping_start + size; } if (dmem_area == dmem_map.end()) { From c01590175a8f04e90a5daa1d785a4dbb48e4b012 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Thu, 24 Apr 2025 22:13:44 +0200 Subject: [PATCH 39/41] Implement sceImeDialogGetPanelSize (#2839) * Implement sceImeDialogGetPanelSize * Fix header * Clang * Adjust values that are different from Ime * Add original sizes as comments * clang * At this point half of the PR is from squidbus, and I'm just typing out what they say --------- Co-authored-by: squidbus <175574877+squidbus@users.noreply.github.com> --- src/core/libraries/ime/ime_dialog.cpp | 32 ++++++++++++++++++++++++--- src/core/libraries/ime/ime_dialog.h | 3 ++- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/core/libraries/ime/ime_dialog.cpp b/src/core/libraries/ime/ime_dialog.cpp index 9151aa64e..bee185787 100644 --- a/src/core/libraries/ime/ime_dialog.cpp +++ b/src/core/libraries/ime/ime_dialog.cpp @@ -83,9 +83,35 @@ int PS4_SYSV_ABI sceImeDialogGetPanelPositionAndForm() { return ORBIS_OK; } -int PS4_SYSV_ABI sceImeDialogGetPanelSize() { - LOG_ERROR(Lib_ImeDialog, "(STUBBED) called"); - return ORBIS_OK; +Error PS4_SYSV_ABI sceImeDialogGetPanelSize(const OrbisImeDialogParam* param, u32* width, + u32* height) { + LOG_INFO(Lib_ImeDialog, "called"); + + if (!width || !height) { + return Error::INVALID_ADDRESS; + } + switch (param->type) { + case OrbisImeType::Default: + case OrbisImeType::BasicLatin: + case OrbisImeType::Url: + case OrbisImeType::Mail: + *width = 500; // original: 793 + if (True(param->option & OrbisImeDialogOption::Multiline)) { + *height = 300; // original: 576 + } else { + *height = 150; // original: 476 + } + break; + case OrbisImeType::Number: + *width = 370; + *height = 470; + break; + default: + LOG_ERROR(Lib_ImeDialog, "Unknown OrbisImeType: {}", (u32)param->type); + return Error::INVALID_PARAM; + } + + return Error::OK; } int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended() { diff --git a/src/core/libraries/ime/ime_dialog.h b/src/core/libraries/ime/ime_dialog.h index c8b228498..33abc7ecd 100644 --- a/src/core/libraries/ime/ime_dialog.h +++ b/src/core/libraries/ime/ime_dialog.h @@ -155,7 +155,8 @@ Error PS4_SYSV_ABI sceImeDialogForceClose(); Error PS4_SYSV_ABI sceImeDialogForTestFunction(); int PS4_SYSV_ABI sceImeDialogGetCurrentStarState(); int PS4_SYSV_ABI sceImeDialogGetPanelPositionAndForm(); -int PS4_SYSV_ABI sceImeDialogGetPanelSize(); +Error PS4_SYSV_ABI sceImeDialogGetPanelSize(const OrbisImeDialogParam* param, u32* width, + u32* height); int PS4_SYSV_ABI sceImeDialogGetPanelSizeExtended(); Error PS4_SYSV_ABI sceImeDialogGetResult(OrbisImeDialogResult* result); OrbisImeDialogStatus PS4_SYSV_ABI sceImeDialogGetStatus(); From d370ea32f4d0e7a00e87ef104d2bde22eaa9c343 Mon Sep 17 00:00:00 2001 From: Dmugetsu <168934208+diegolix29@users.noreply.github.com> Date: Thu, 24 Apr 2025 15:46:22 -0600 Subject: [PATCH 40/41] Sysmodules (#2826) * Some sysmodules inconsistencies fixed. Based on Visual studio flags if they are irrelevant lmk * Suggestions - info passed to sceKernelGetModuleInfoForUnwind and if name field matches it gets zeroed * Final suggestions * reverting OrbisModuleInfoForUnwind and modifing header. --- src/core/libraries/system/sysmodule.cpp | 40 +++++++++++++++++++++---- src/core/libraries/system/sysmodule.h | 4 ++- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/core/libraries/system/sysmodule.cpp b/src/core/libraries/system/sysmodule.cpp index 6c73764f2..d9e78e4ab 100644 --- a/src/core/libraries/system/sysmodule.cpp +++ b/src/core/libraries/system/sysmodule.cpp @@ -19,11 +19,40 @@ int PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal() { return ORBIS_OK; } -s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, void* info) { - LOG_ERROR(Lib_SysModule, "(STUBBED) called"); - Kernel::OrbisModuleInfoForUnwind module_info; - module_info.st_size = 0x130; - s32 res = Kernel::sceKernelGetModuleInfoForUnwind(addr, flags, &module_info); +s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, + Kernel::OrbisModuleInfoForUnwind* info) { + LOG_TRACE(Lib_SysModule, "sceSysmoduleGetModuleInfoForUnwind(addr=0x{:X}, flags=0x{:X})", addr, + flags); + + s32 res = Kernel::sceKernelGetModuleInfoForUnwind(addr, flags, info); + if (res != 0) { + return res; + } + + static constexpr std::array modules_to_hide = { + "libc.prx", + "libc.sprx", + "libSceAudioLatencyEstimation.prx", + "libSceFace.prx", + "libSceFaceTracker.prx", + "libSceFios2.prx", + "libSceFios2.sprx", + "libSceFontGsm.prx", + "libSceHand.prx", + "libSceHandTracker.prx", + "libSceHeadTracker.prx", + "libSceJobManager.prx", + "libSceNpCppWebApi.prx", + "libSceNpToolkit.prx", + "libSceNpToolkit2.prx", + "libSceS3DConversion.prx", + "libSceSmart.prx", + }; + + const std::string_view module_name = info->name.data(); + if (std::ranges::find(modules_to_hide, module_name) != modules_to_hide.end()) { + std::ranges::fill(info->name, '\0'); + } return res; } @@ -56,7 +85,6 @@ int PS4_SYSV_ABI sceSysmoduleIsLoadedInternal(OrbisSysModuleInternal id) { } int PS4_SYSV_ABI sceSysmoduleLoadModule(OrbisSysModule id) { - auto color_name = magic_enum::enum_name(id); LOG_ERROR(Lib_SysModule, "(DUMMY) called module = {}", magic_enum::enum_name(id)); return ORBIS_OK; } diff --git a/src/core/libraries/system/sysmodule.h b/src/core/libraries/system/sysmodule.h index dfbdca162..9a5fe9513 100644 --- a/src/core/libraries/system/sysmodule.h +++ b/src/core/libraries/system/sysmodule.h @@ -4,6 +4,7 @@ #pragma once #include "common/types.h" +#include "core/libraries/kernel/process.h" namespace Core::Loader { class SymbolsResolver; @@ -152,7 +153,8 @@ enum class OrbisSysModuleInternal : u32 { }; int PS4_SYSV_ABI sceSysmoduleGetModuleHandleInternal(); -s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, void* info); +s32 PS4_SYSV_ABI sceSysmoduleGetModuleInfoForUnwind(VAddr addr, s32 flags, + Kernel::OrbisModuleInfoForUnwind* info); int PS4_SYSV_ABI sceSysmoduleIsCalledFromSysModule(); int PS4_SYSV_ABI sceSysmoduleIsCameraPreloaded(); int PS4_SYSV_ABI sceSysmoduleIsLoaded(OrbisSysModule id); From 15d6a45dcdf49bbd232e0ef275373c9b1018a839 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Thu, 24 Apr 2025 19:40:50 -0700 Subject: [PATCH 41/41] externals: Simplify MoltenVK bundling. (#2842) --- CMakeLists.txt | 32 +++++++++++++++----------------- externals/MoltenVK/MoltenVK | 2 +- externals/MoltenVK/SPIRV-Cross | 2 +- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3561c2c3a..96cce0b10 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1084,33 +1084,31 @@ endif() if (APPLE) # Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers. - set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) - if (ENABLE_QT_GUI) - set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks") - set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json) - set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib) - set(MVK_DYLIB_ICD_PATH "../../../Frameworks/libMoltenVK.dylib") + set(MVK_BUNDLE_PATH "Resources/vulkan/icd.d") + set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../${MVK_BUNDLE_PATH}") + set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/${MVK_BUNDLE_PATH}) else() set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path") - set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/MoltenVK_icd.json) - set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/libMoltenVK.dylib) - set(MVK_DYLIB_ICD_PATH "./libMoltenVK.dylib") + set(MVK_DST ${CMAKE_CURRENT_BINARY_DIR}) endif() - cmake_path(GET MVK_ICD_DST PARENT_PATH MVK_ICD_DST_PARENT) - cmake_path(GET MVK_DYLIB_DST PARENT_PATH MVK_DYLIB_DST_PARENT) + set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) + set(MVK_DYLIB_DST ${MVK_DST}/libMoltenVK.dylib) + set(MVK_ICD_SRC ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK/MoltenVK/icd/MoltenVK_icd.json) + set(MVK_ICD_DST ${MVK_DST}/MoltenVK_icd.json) - set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.3.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}") + add_custom_command( + OUTPUT ${MVK_DST} + COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DST}) add_custom_command( OUTPUT ${MVK_ICD_DST} - COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_ICD_DST_PARENT} && ${CMAKE_COMMAND} -E echo ${MVK_ICD} > ${MVK_ICD_DST}) - + DEPENDS ${MVK_ICD_SRC} ${MVK_DST} + COMMAND ${CMAKE_COMMAND} -E copy ${MVK_ICD_SRC} ${MVK_ICD_DST}) add_custom_command( OUTPUT ${MVK_DYLIB_DST} - DEPENDS ${MVK_DYLIB_SRC} - COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DYLIB_DST_PARENT} && ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) - + DEPENDS ${MVK_DYLIB_SRC} ${MVK_DST} + COMMAND ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) add_custom_target(CopyMoltenVK DEPENDS ${MVK_ICD_DST} ${MVK_DYLIB_DST}) add_dependencies(CopyMoltenVK MoltenVK) add_dependencies(shadps4 CopyMoltenVK) diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 4cf8f9468..87a8e8b13 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 4cf8f94684c53e581eb9cc694dd3305d1f7d9959 +Subproject commit 87a8e8b13d4ad8835367fea1ebad1896d0460946 diff --git a/externals/MoltenVK/SPIRV-Cross b/externals/MoltenVK/SPIRV-Cross index 2275d0efc..791877574 160000 --- a/externals/MoltenVK/SPIRV-Cross +++ b/externals/MoltenVK/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 2275d0efc4f2fa46851035d9d3c67c105bc8b99e +Subproject commit 7918775748c5e2f5c40d9918ce68825035b5a1e1