Merge branch 'shadps4-emu:main' into qt-style

This commit is contained in:
tomboylover93 2025-01-24 15:39:00 -08:00 committed by GitHub
commit e72f0dd235
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
40 changed files with 869 additions and 364 deletions

View File

@ -24,27 +24,20 @@ jobs:
runs-on: ubuntu-24.04
continue-on-error: true
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-18 main'
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: clang-format-18
version: 1.0
sudo apt update
sudo apt install clang-format-18
- name: Build
env:
COMMIT_RANGE: ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
run: ./.ci/clang-format.sh
get-info:
runs-on: ubuntu-24.04
outputs:
@ -289,13 +282,7 @@ jobs:
submodules: recursive
- name: Install dependencies
run: |
sudo apt install -y libfuse2
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev clang build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
version: 1.0
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -351,13 +338,7 @@ jobs:
submodules: recursive
- name: Install dependencies
run: |
sudo apt install -y libfuse2 qt6-base-dev qt6-tools-dev qt6-multimedia-dev
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev clang build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
version: 1.0
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 clang build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -404,13 +385,7 @@ jobs:
submodules: recursive
- name: Install dependencies
run: |
sudo apt install -y libfuse2
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev gcc-14 build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
version: 1.0
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -446,13 +421,7 @@ jobs:
submodules: recursive
- name: Install dependencies
run: |
sudo apt install -y libfuse2 qt6-base-dev qt6-tools-dev qt6-multimedia-dev
- uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev gcc-14 build-essential libasound2-dev libpulse-dev libopenal-dev libudev-dev
version: 1.0
run: sudo apt-get update && sudo apt install -y libx11-dev libxext-dev libwayland-dev libdecor-0-dev libxkbcommon-dev libglfw3-dev libgles2-mesa-dev libfuse2 gcc-14 build-essential qt6-base-dev qt6-tools-dev qt6-multimedia-dev libasound2-dev libpulse-dev libopenal-dev libudev-dev
- name: Cache CMake Configuration
uses: actions/cache@v4
@ -474,8 +443,7 @@ jobs:
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
- name: Configure CMake
run: |
cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
run: cmake --fresh -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 -DENABLE_QT_GUI=ON -DENABLE_UPDATER=ON -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel $(nproc)

View File

@ -344,6 +344,8 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
src/core/libraries/razor_cpu/razor_cpu.h
src/core/libraries/mouse/mouse.cpp
src/core/libraries/mouse/mouse.h
src/core/libraries/web_browser_dialog/webbrowserdialog.cpp
src/core/libraries/web_browser_dialog/webbrowserdialog.h
)
set(VIDEOOUT_LIB src/core/libraries/videoout/buffer.h
@ -434,6 +436,8 @@ set(NP_LIBS src/core/libraries/np_common/np_common.cpp
src/core/libraries/np_trophy/np_trophy_error.h
src/core/libraries/np_web_api/np_web_api.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
)
set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
@ -751,8 +755,6 @@ set(VIDEO_CORE src/video_core/amdgpu/liverpool.cpp
src/video_core/renderer_vulkan/vk_common.h
src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
src/video_core/renderer_vulkan/vk_compute_pipeline.h
src/video_core/renderer_vulkan/vk_descriptor_update_queue.cpp
src/video_core/renderer_vulkan/vk_descriptor_update_queue.h
src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
src/video_core/renderer_vulkan/vk_graphics_pipeline.h
src/video_core/renderer_vulkan/vk_instance.cpp

View File

@ -22,7 +22,10 @@ SPDX-License-Identifier: GPL-2.0-or-later
- A processor with at least 4 cores and 6 threads
- Above 2.5 GHz frequency
- required support AVX2 extension or Rosetta 2 on ARM
- A CPU supporting the following instruction sets: MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, F16C, CLMUL, AES, BMI1, MOVBE, XSAVE, ABM
- **Intel**: Haswell generation or newer
- **AMD**: Jaguar generation or newer
- **Apple**: Rosetta 2 on macOS 15 or newer
### GPU

View File

@ -29,7 +29,8 @@ sudo dnf install clang git cmake libatomic alsa-lib-devel pipewire-jack-audio-co
sudo pacman -S base-devel clang git cmake sndio jack2 openal qt6-base qt6-declarative qt6-multimedia sdl2 vulkan-validation-layers
```
**Note**: The `shadps4-git` AUR package is not maintained by any of the developers, and it uses GCC as the compiler as opposed to Clang. Use at your own discretion.
**Note** : The `shadps4-git` AUR package is not maintained by any of the developers, and it uses the default compiler, which is often set to GCC. Use at your own discretion.
#### OpenSUSE
```
@ -49,6 +50,7 @@ distrobox create --name archlinux --init --image archlinux:latest
and install the dependencies on that container as cited above.
This option is **highly recommended** for NixOS and distributions with immutable/atomic filesystems (example: Fedora Kinoite, SteamOS).
### Cloning
```

@ -1 +1 @@
Subproject commit 9f0b616d9e2c39464d2a859b79dbc655c4a30e7e
Subproject commit 2473ce6f0ab7d5d8a49aa91b2e37f3447a939f18

@ -1 +1 @@
Subproject commit 6173e24b31f09a0c3217103a130e74c4ddec14a6
Subproject commit 1a7b7ef6de02cf6767e42b10ddad217c45e90d47

2
externals/sdl3 vendored

@ -1 +1 @@
Subproject commit 22422f7748d5128135995ed34c8f8012861c7332
Subproject commit a336b62d8b0b97b09214e053203e442e2b6e2be5

2
externals/sirit vendored

@ -1 +1 @@
Subproject commit 26ad5a9d0fe13260b0d7d6c64419d01a196b2e32
Subproject commit d6f3c0d99862ab2ff8f95e9ac221560f1f97e29a

View File

@ -131,6 +131,8 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Lib, Videodec) \
SUB(Lib, RazorCpu) \
SUB(Lib, Mouse) \
SUB(Lib, WebBrowserDialog) \
SUB(Lib, NpParty) \
CLS(Frontend) \
CLS(Render) \
SUB(Render, Vulkan) \

View File

@ -98,6 +98,8 @@ enum class Class : u8 {
Lib_Videodec, ///< The LibSceVideodec implementation.
Lib_RazorCpu, ///< The LibRazorCpu implementation.
Lib_Mouse, ///< The LibSceMouse implementation
Lib_WebBrowserDialog, ///< The LibSceWebBrowserDialog implementation
Lib_NpParty, ///< The LibSceNpParty implementation
Frontend, ///< Emulator UI
Render, ///< Video Core
Render_Vulkan, ///< Vulkan backend

View File

@ -37,8 +37,9 @@ extern "C" void PS4_SYSV_ABI _sceFiberForceQuit(u64 ret) {
void PS4_SYSV_ABI _sceFiberCheckStackOverflow(OrbisFiberContext* ctx) {
u64* stack_base = reinterpret_cast<u64*>(ctx->current_fiber->addr_context);
u64 stack_size = ctx->current_fiber->size_context;
if (stack_base && *stack_base != kFiberStackSignature) {
UNREACHABLE_MSG("Stack overflow detected in fiber.");
UNREACHABLE_MSG("Stack overflow detected in fiber with size = 0x{:x}", stack_size);
}
}

View File

@ -28,6 +28,7 @@
#include "core/libraries/network/ssl2.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"
#include "core/libraries/np_score/np_score.h"
#include "core/libraries/np_trophy/np_trophy.h"
#include "core/libraries/np_web_api/np_web_api.h"
@ -52,6 +53,7 @@
#include "core/libraries/videodec/videodec.h"
#include "core/libraries/videodec/videodec2.h"
#include "core/libraries/videoout/video_out.h"
#include "core/libraries/web_browser_dialog/webbrowserdialog.h"
#include "fiber/fiber.h"
#include "jpeg/jpegenc.h"
@ -107,6 +109,8 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
Libraries::Fiber::RegisterlibSceFiber(sym);
Libraries::JpegEnc::RegisterlibSceJpegEnc(sym);
Libraries::Mouse::RegisterlibSceMouse(sym);
Libraries::WebBrowserDialog::RegisterlibSceWebBrowserDialog(sym);
Libraries::NpParty::RegisterlibSceNpParty(sym);
}
} // namespace Libraries

View File

@ -0,0 +1,195 @@
// 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_party/np_party.h"
namespace Libraries::NpParty {
s32 PS4_SYSV_ABI sceNpPartyCheckCallback() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyCreate() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyCreateA() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetId() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetMemberInfo() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetMemberInfoA() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetMembers() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetMembersA() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetMemberSessionInfo() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetMemberVoiceInfo() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetState() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetStateAsUser() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetStateAsUserA() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyGetVoiceChatPriority() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyInitialize() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyJoin() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyLeave() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyRegisterHandler() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyRegisterHandlerA() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyRegisterPrivateHandler() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartySendBinaryMessage() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartySetVoiceChatPriority() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyShowInvitationList() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyShowInvitationListA() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyTerminate() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceNpPartyUnregisterPrivateHandler() {
LOG_ERROR(Lib_NpParty, "(STUBBED) called");
return ORBIS_OK;
}
void RegisterlibSceNpParty(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("3e4k2mzLkmc", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyCheckCallback);
LIB_FUNCTION("nOZRy-slBoA", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyCreate);
LIB_FUNCTION("XQSUbbnpPBA", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyCreateA);
LIB_FUNCTION("DRA3ay-1DFQ", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyGetId);
LIB_FUNCTION("F1P+-wpxQow", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyGetMemberInfo);
LIB_FUNCTION("v2RYVGrJDkM", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyGetMemberInfoA);
LIB_FUNCTION("T2UOKf00ZN0", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyGetMembers);
LIB_FUNCTION("TaNw7W25QJw", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyGetMembersA);
LIB_FUNCTION("4gOMfNYzllw", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyGetMemberSessionInfo);
LIB_FUNCTION("EKi1jx59SP4", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyGetMemberVoiceInfo);
LIB_FUNCTION("aEzKdJzATZ0", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyGetState);
LIB_FUNCTION("o7grRhiGHYI", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyGetStateAsUser);
LIB_FUNCTION("EjyAI+QNgFw", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyGetStateAsUserA);
LIB_FUNCTION("-lc6XZnQXvM", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyGetVoiceChatPriority);
LIB_FUNCTION("lhYCTQmBkds", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyInitialize);
LIB_FUNCTION("RXNCDw2GDEg", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyJoin);
LIB_FUNCTION("J8jAi-tfJHc", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyLeave);
LIB_FUNCTION("kA88gbv71ao", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyRegisterHandler);
LIB_FUNCTION("+v4fVHMwFWc", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyRegisterHandlerA);
LIB_FUNCTION("zo4G5WWYpKg", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyRegisterPrivateHandler);
LIB_FUNCTION("U6VdUe-PNAY", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartySendBinaryMessage);
LIB_FUNCTION("nazKyHygHhY", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartySetVoiceChatPriority);
LIB_FUNCTION("-MFiL7hEnPE", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyShowInvitationList);
LIB_FUNCTION("yARHEYLajs0", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyShowInvitationListA);
LIB_FUNCTION("oLYkibiHqRA", "libSceNpParty", 1, "libSceNpParty", 1, 1, sceNpPartyTerminate);
LIB_FUNCTION("zQ7gIvt11Pc", "libSceNpParty", 1, "libSceNpParty", 1, 1,
sceNpPartyUnregisterPrivateHandler);
LIB_FUNCTION("nOZRy-slBoA", "libSceNpPartyCompat", 1, "libSceNpParty", 1, 1, sceNpPartyCreate);
LIB_FUNCTION("F1P+-wpxQow", "libSceNpPartyCompat", 1, "libSceNpParty", 1, 1,
sceNpPartyGetMemberInfo);
LIB_FUNCTION("T2UOKf00ZN0", "libSceNpPartyCompat", 1, "libSceNpParty", 1, 1,
sceNpPartyGetMembers);
LIB_FUNCTION("o7grRhiGHYI", "libSceNpPartyCompat", 1, "libSceNpParty", 1, 1,
sceNpPartyGetStateAsUser);
LIB_FUNCTION("kA88gbv71ao", "libSceNpPartyCompat", 1, "libSceNpParty", 1, 1,
sceNpPartyRegisterHandler);
LIB_FUNCTION("-MFiL7hEnPE", "libSceNpPartyCompat", 1, "libSceNpParty", 1, 1,
sceNpPartyShowInvitationList);
};
} // namespace Libraries::NpParty

View File

@ -0,0 +1,44 @@
// 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::NpParty {
s32 PS4_SYSV_ABI sceNpPartyCheckCallback();
s32 PS4_SYSV_ABI sceNpPartyCreate();
s32 PS4_SYSV_ABI sceNpPartyCreateA();
s32 PS4_SYSV_ABI sceNpPartyGetId();
s32 PS4_SYSV_ABI sceNpPartyGetMemberInfo();
s32 PS4_SYSV_ABI sceNpPartyGetMemberInfoA();
s32 PS4_SYSV_ABI sceNpPartyGetMembers();
s32 PS4_SYSV_ABI sceNpPartyGetMembersA();
s32 PS4_SYSV_ABI sceNpPartyGetMemberSessionInfo();
s32 PS4_SYSV_ABI sceNpPartyGetMemberVoiceInfo();
s32 PS4_SYSV_ABI sceNpPartyGetState();
s32 PS4_SYSV_ABI sceNpPartyGetStateAsUser();
s32 PS4_SYSV_ABI sceNpPartyGetStateAsUserA();
s32 PS4_SYSV_ABI sceNpPartyGetVoiceChatPriority();
s32 PS4_SYSV_ABI sceNpPartyInitialize();
s32 PS4_SYSV_ABI sceNpPartyJoin();
s32 PS4_SYSV_ABI sceNpPartyLeave();
s32 PS4_SYSV_ABI sceNpPartyRegisterHandler();
s32 PS4_SYSV_ABI sceNpPartyRegisterHandlerA();
s32 PS4_SYSV_ABI sceNpPartyRegisterPrivateHandler();
s32 PS4_SYSV_ABI sceNpPartySendBinaryMessage();
s32 PS4_SYSV_ABI sceNpPartySetVoiceChatPriority();
s32 PS4_SYSV_ABI sceNpPartyShowInvitationList();
s32 PS4_SYSV_ABI sceNpPartyShowInvitationListA();
s32 PS4_SYSV_ABI sceNpPartyTerminate();
s32 PS4_SYSV_ABI sceNpPartyUnregisterPrivateHandler();
s32 PS4_SYSV_ABI module_start();
s32 PS4_SYSV_ABI module_stop();
void RegisterlibSceNpParty(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::NpParty

View File

@ -0,0 +1,112 @@
// 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/web_browser_dialog/webbrowserdialog.h"
namespace Libraries::WebBrowserDialog {
s32 PS4_SYSV_ABI sceWebBrowserDialogClose() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogGetEvent() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogGetResult() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogGetStatus() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogInitialize() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogNavigate() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogOpen() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogOpenForPredeterminedContent() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogResetCookie() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogSetCookie() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogSetZoom() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogTerminate() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceWebBrowserDialogUpdateStatus() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI Func_F2BE042771625F8C() {
LOG_ERROR(Lib_WebBrowserDialog, "(STUBBED) called");
return ORBIS_OK;
}
void RegisterlibSceWebBrowserDialog(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("PSK+Eik919Q", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogClose);
LIB_FUNCTION("Wit4LjeoeX4", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogGetEvent);
LIB_FUNCTION("vCaW0fgVQmc", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogGetResult);
LIB_FUNCTION("CFTG6a8TjOU", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogGetStatus);
LIB_FUNCTION("jqb7HntFQFc", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogInitialize);
LIB_FUNCTION("uYELOMVnmNQ", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogNavigate);
LIB_FUNCTION("FraP7debcdg", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogOpen);
LIB_FUNCTION("O7dIZQrwVFY", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogOpenForPredeterminedContent);
LIB_FUNCTION("Cya+jvTtPqg", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogResetCookie);
LIB_FUNCTION("TZnDVkP91Rg", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogSetCookie);
LIB_FUNCTION("RLhKBOoNyXY", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogSetZoom);
LIB_FUNCTION("ocHtyBwHfys", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogTerminate);
LIB_FUNCTION("h1dR-t5ISgg", "libSceWebBrowserDialog", 1, "libSceWebBrowserDialog", 1, 1,
sceWebBrowserDialogUpdateStatus);
LIB_FUNCTION("8r4EJ3FiX4w", "libSceWebBrowserDialogLimited", 1, "libSceWebBrowserDialog", 1, 1,
Func_F2BE042771625F8C);
};
} // namespace Libraries::WebBrowserDialog

View File

@ -0,0 +1,30 @@
// 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::WebBrowserDialog {
s32 PS4_SYSV_ABI sceWebBrowserDialogClose();
s32 PS4_SYSV_ABI sceWebBrowserDialogGetEvent();
s32 PS4_SYSV_ABI sceWebBrowserDialogGetResult();
s32 PS4_SYSV_ABI sceWebBrowserDialogGetStatus();
s32 PS4_SYSV_ABI sceWebBrowserDialogInitialize();
s32 PS4_SYSV_ABI sceWebBrowserDialogNavigate();
s32 PS4_SYSV_ABI sceWebBrowserDialogOpen();
s32 PS4_SYSV_ABI sceWebBrowserDialogOpenForPredeterminedContent();
s32 PS4_SYSV_ABI sceWebBrowserDialogResetCookie();
s32 PS4_SYSV_ABI sceWebBrowserDialogSetCookie();
s32 PS4_SYSV_ABI sceWebBrowserDialogSetZoom();
s32 PS4_SYSV_ABI sceWebBrowserDialogTerminate();
s32 PS4_SYSV_ABI sceWebBrowserDialogUpdateStatus();
s32 PS4_SYSV_ABI Func_F2BE042771625F8C();
void RegisterlibSceWebBrowserDialog(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::WebBrowserDialog

View File

@ -389,47 +389,57 @@ s32 MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) {
return UnmapMemoryImpl(virtual_addr, size);
}
s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, size_t size) {
const auto it = FindVMA(virtual_addr);
const auto& vma_base = it->second;
ASSERT_MSG(vma_base.Contains(virtual_addr, size),
"Existing mapping does not contain requested unmap range");
const auto type = vma_base.type;
if (type == VMAType::Free) {
return ORBIS_OK;
}
u64 MemoryManager::UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base, u64 size) {
const auto vma_base_addr = vma_base.base;
const auto vma_base_size = vma_base.size;
const auto type = vma_base.type;
const auto phys_base = vma_base.phys_base;
const bool is_exec = vma_base.is_exec;
const auto start_in_vma = virtual_addr - vma_base_addr;
const auto adjusted_size =
vma_base_size - start_in_vma < size ? vma_base_size - start_in_vma : size;
const bool has_backing = type == VMAType::Direct || type == VMAType::File;
if (type == VMAType::Free) {
return adjusted_size;
}
if (type == VMAType::Direct || type == VMAType::Pooled) {
rasterizer->UnmapMemory(virtual_addr, size);
rasterizer->UnmapMemory(virtual_addr, adjusted_size);
}
if (type == VMAType::Flexible) {
flexible_usage -= size;
flexible_usage -= adjusted_size;
}
// Mark region as free and attempt to coalesce it with neighbours.
const auto new_it = CarveVMA(virtual_addr, size);
const auto new_it = CarveVMA(virtual_addr, adjusted_size);
auto& vma = new_it->second;
vma.type = VMAType::Free;
vma.prot = MemoryProt::NoAccess;
vma.phys_base = 0;
vma.disallow_merge = false;
vma.name = "";
MergeAdjacent(vma_map, new_it);
bool readonly_file = vma.prot == MemoryProt::CpuRead && type == VMAType::File;
const auto post_merge_it = MergeAdjacent(vma_map, new_it);
auto& post_merge_vma = post_merge_it->second;
bool readonly_file = post_merge_vma.prot == MemoryProt::CpuRead && type == VMAType::File;
if (type != VMAType::Reserved && type != VMAType::PoolReserved) {
// Unmap the memory region.
impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base,
is_exec, has_backing, readonly_file);
impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + adjusted_size,
phys_base, is_exec, has_backing, readonly_file);
TRACK_FREE(virtual_addr, "VMEM");
}
return adjusted_size;
}
s32 MemoryManager::UnmapMemoryImpl(VAddr virtual_addr, u64 size) {
u64 unmapped_bytes = 0;
do {
auto it = FindVMA(virtual_addr + unmapped_bytes);
auto& vma_base = it->second;
auto unmapped =
UnmapBytesFromEntry(virtual_addr + unmapped_bytes, vma_base, size - unmapped_bytes);
ASSERT_MSG(unmapped > 0, "Failed to unmap memory, progress is impossible");
unmapped_bytes += unmapped;
} while (unmapped_bytes < size);
return ORBIS_OK;
}
@ -651,6 +661,12 @@ MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, size_t size
const VAddr start_in_vma = virtual_addr - vma.base;
const VAddr end_in_vma = start_in_vma + size;
if (start_in_vma == 0 && size == vma.size) {
// if requsting the whole VMA, return it
return vma_handle;
}
ASSERT_MSG(end_in_vma <= vma.size, "Mapping cannot fit inside free region");
if (end_in_vma != vma.size) {

View File

@ -252,7 +252,9 @@ private:
DMemHandle Split(DMemHandle dmem_handle, size_t offset_in_area);
s32 UnmapMemoryImpl(VAddr virtual_addr, size_t size);
u64 UnmapBytesFromEntry(VAddr virtual_addr, VirtualMemoryArea vma_base, u64 size);
s32 UnmapMemoryImpl(VAddr virtual_addr, u64 size);
private:
AddressSpace impl;

View File

@ -146,14 +146,14 @@ void CheckUpdate::CheckForUpdates(const bool showMessage) {
}
QString currentRev = (updateChannel == "Nightly")
? QString::fromStdString(Common::g_scm_rev).left(7)
? QString::fromStdString(Common::g_scm_rev)
: "v." + QString::fromStdString(Common::VERSION);
QString currentDate = Common::g_scm_date;
QDateTime dateTime = QDateTime::fromString(latestDate, Qt::ISODate);
latestDate = dateTime.isValid() ? dateTime.toString("yyyy-MM-dd HH:mm:ss") : "Unknown date";
if (latestRev == currentRev) {
if (latestRev == currentRev.left(7)) {
if (showMessage) {
QMessageBox::information(this, tr("Auto Updater"),
tr("Your version is already up to date!"));
@ -190,7 +190,7 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
QString("<p><b><br>" + tr("Update Channel") + ": </b>" + updateChannel + "<br><b>" +
tr("Current Version") + ":</b> %1 (%2)<br><b>" + tr("Latest Version") +
":</b> %3 (%4)</p><p>" + tr("Do you want to update?") + "</p>")
.arg(currentRev, currentDate, latestRev, latestDate);
.arg(currentRev.left(7), currentDate, latestRev, latestDate);
QLabel* updateLabel = new QLabel(updateText, this);
layout->addWidget(updateLabel);

View File

@ -52,7 +52,7 @@
</message>
<message>
<source>Select which directory you want to install to.</source>
<translation>Select which directory you want to install to.</translation>
<translation>Wybierz katalog, do którego chcesz zainstalować.</translation>
</message>
</context>
<context>
@ -130,35 +130,35 @@
</message>
<message>
<source>Delete...</source>
<translation>Delete...</translation>
<translation>Usuń...</translation>
</message>
<message>
<source>Delete Game</source>
<translation>Delete Game</translation>
<translation>Usuń Grę</translation>
</message>
<message>
<source>Delete Update</source>
<translation>Delete Update</translation>
<translation>Usuń Aktualizację</translation>
</message>
<message>
<source>Delete DLC</source>
<translation>Delete DLC</translation>
<translation>Usuń DLC</translation>
</message>
<message>
<source>Compatibility...</source>
<translation>Compatibility...</translation>
<translation>kompatybilność...</translation>
</message>
<message>
<source>Update database</source>
<translation>Update database</translation>
<translation>Zaktualizuj bazę danych</translation>
</message>
<message>
<source>View report</source>
<translation>View report</translation>
<translation>Wyświetl zgłoszenie</translation>
</message>
<message>
<source>Submit a report</source>
<translation>Submit a report</translation>
<translation>Wyślij zgłoszenie</translation>
</message>
<message>
<source>Shortcut creation</source>
@ -182,23 +182,23 @@
</message>
<message>
<source>Game</source>
<translation>Game</translation>
<translation>Gra</translation>
</message>
<message>
<source>requiresEnableSeparateUpdateFolder_MSG</source>
<translation>This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it.</translation>
<translation>Ta funkcja wymaga do działania opcji Włącz oddzielny folder aktualizacji. Jeśli chcesz korzystać z tej funkcji, włącz .</translation>
</message>
<message>
<source>This game has no update to delete!</source>
<translation>This game has no update to delete!</translation>
<translation>Ta gra nie ma aktualizacji do usunięcia!</translation>
</message>
<message>
<source>Update</source>
<translation>Update</translation>
<translation>Aktualizacja</translation>
</message>
<message>
<source>This game has no DLC to delete!</source>
<translation>This game has no DLC to delete!</translation>
<translation>Ta gra nie ma DLC do usunięcia!</translation>
</message>
<message>
<source>DLC</source>
@ -206,11 +206,11 @@
</message>
<message>
<source>Delete %1</source>
<translation>Delete %1</translation>
<translation>Usuń %1</translation>
</message>
<message>
<source>Are you sure you want to delete %1's %2 directory?</source>
<translation>Are you sure you want to delete %1's %2 directory?</translation>
<translation>Czy na pewno chcesz usunąć katalog %1 z %2?</translation>
</message>
</context>
<context>
@ -249,7 +249,7 @@
</message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
<translation>Otwórz folder shadPS4</translation>
</message>
<message>
<source>Exit</source>
@ -546,7 +546,7 @@
</message>
<message>
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
<translation>Włącz oddzielny folder aktualizacji</translation>
</message>
<message>
<source>Default tab when opening settings</source>
@ -574,11 +574,11 @@
</message>
<message>
<source>Trophy Key</source>
<translation>Trophy Key</translation>
<translation>Klucz trofeów</translation>
</message>
<message>
<source>Trophy</source>
<translation>Trophy</translation>
<translation>Trofeum</translation>
</message>
<message>
<source>Logger</source>
@ -722,7 +722,7 @@
</message>
<message>
<source>Disable Trophy Pop-ups</source>
<translation>Disable Trophy Pop-ups</translation>
<translation>Wyłącz wyskakujące okienka trofeów</translation>
</message>
<message>
<source>Play title music</source>
@ -730,19 +730,19 @@
</message>
<message>
<source>Update Compatibility Database On Startup</source>
<translation>Update Compatibility Database On Startup</translation>
<translation>Aktualizuj bazę danych zgodności podczas uruchamiania</translation>
</message>
<message>
<source>Game Compatibility</source>
<translation>Game Compatibility</translation>
<translation>Kompatybilność gier</translation>
</message>
<message>
<source>Display Compatibility Data</source>
<translation>Display Compatibility Data</translation>
<translation>Wyświetl dane zgodności</translation>
</message>
<message>
<source>Update Compatibility Database</source>
<translation>Update Compatibility Database</translation>
<translation>Aktualizuj bazę danych zgodności</translation>
</message>
<message>
<source>Volume</source>
@ -750,7 +750,7 @@
</message>
<message>
<source>Audio Backend</source>
<translation>Audio Backend</translation>
<translation>Zaplecze audio</translation>
</message>
<message>
<source>Save</source>
@ -786,7 +786,7 @@
</message>
<message>
<source>separateUpdatesCheckBox</source>
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation>
<translation>Włącz oddzielny folder aktualizacji:\nUmożliwia instalowanie aktualizacji gier w oddzielnym folderze w celu łatwego zarządzania.</translation>
</message>
<message>
<source>showSplashCheckBox</source>
@ -798,7 +798,7 @@
</message>
<message>
<source>discordRPCCheckbox</source>
<translation>Włącz Discord Rich Presence:\nWyświetla ikonę emuladora i odpowiednie informacje na twoim profilu Discord.</translation>
<translation>Włącz Discord Rich Presence:\nWyświetla ikonę emulatora i odpowiednie informacje na twoim profilu Discord.</translation>
</message>
<message>
<source>userName</source>
@ -806,7 +806,7 @@
</message>
<message>
<source>TrophyKey</source>
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
<translation>Klucz trofeów:\nKlucz używany do odszyfrowywania trofeów. Musi być uzyskany z konsoli po jailbreaku. Musi zawierać tylko znaki w kodzie szesnastkowym.</translation>
</message>
<message>
<source>logTypeGroupBox</source>
@ -826,7 +826,7 @@
</message>
<message>
<source>disableTrophycheckBox</source>
<translation>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).</translation>
<translation>Wyłącz wyskakujące okienka trofeów:\nWyłącz powiadomienia o trofeach w grze. Postępy w zdobywaniu trofeów można nadal śledzić za pomocą przeglądarki trofeów (kliknij prawym przyciskiem myszy grę w oknie głównym).</translation>
</message>
<message>
<source>hideCursorGroupBox</source>
@ -842,15 +842,15 @@
</message>
<message>
<source>enableCompatibilityCheckBox</source>
<translation>Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information.</translation>
<translation>Wyświetl dane zgodności:\nWyświetla informacje o kompatybilności gry w widoku tabeli. Włącz opcję Aktualizuj zgodność przy uruchomieniu, aby uzyskać aktualne informacje.</translation>
</message>
<message>
<source>checkCompatibilityOnStartupCheckBox</source>
<translation>Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts.</translation>
<translation>Aktualizuj zgodność przy uruchomieniu:\nAutomatycznie aktualizuj bazę danych kompatybilności podczas uruchamiania shadPS4.</translation>
</message>
<message>
<source>updateCompatibilityButton</source>
<translation>Update Compatibility Database:\nImmediately update the compatibility database.</translation>
<translation>Zaktualizuj bazę danych zgodności:\nNatychmiast zaktualizuj bazę danych zgodności.</translation>
</message>
<message>
<source>Never</source>
@ -933,7 +933,7 @@
<name>CheatsPatches</name>
<message>
<source>Cheats / Patches for </source>
<translation>Cheats / Patches for </translation>
<translation>Kody / Łatki dla </translation>
</message>
<message>
<source>defaultTextEdit_MSG</source>
@ -1145,7 +1145,7 @@
</message>
<message>
<source>Failed to parse JSON:</source>
<translation>Nie udało się przeanlizować JSON:</translation>
<translation>Nie udało się przeanalizować JSON:</translation>
</message>
<message>
<source>Can't apply cheats before the game is started</source>
@ -1168,7 +1168,7 @@
</message>
<message>
<source>Compatibility</source>
<translation>Compatibility</translation>
<translation>Zgodność</translation>
</message>
<message>
<source>Region</source>
@ -1196,7 +1196,7 @@
</message>
<message>
<source>Never Played</source>
<translation>Never Played</translation>
<translation>Nigdy nie grane</translation>
</message>
<message>
<source>h</source>
@ -1212,27 +1212,27 @@
</message>
<message>
<source>Compatibility is untested</source>
<translation>Compatibility is untested</translation>
<translation>Kompatybilność nie została przetestowana</translation>
</message>
<message>
<source>Game does not initialize properly / crashes the emulator</source>
<translation>Game does not initialize properly / crashes the emulator</translation>
<translation>Gra nie inicjuje się poprawnie / zawiesza się emulator</translation>
</message>
<message>
<source>Game boots, but only displays a blank screen</source>
<translation>Game boots, but only displays a blank screen</translation>
<translation>Gra uruchamia się, ale wyświetla tylko pusty ekran</translation>
</message>
<message>
<source>Game displays an image but does not go past the menu</source>
<translation>Game displays an image but does not go past the menu</translation>
<translation>Gra wyświetla obraz, ale nie przechodzi do menu</translation>
</message>
<message>
<source>Game has game-breaking glitches or unplayable performance</source>
<translation>Game has game-breaking glitches or unplayable performance</translation>
<translation>Gra ma usterki przerywające rozgrywkę lub niegrywalną wydajność</translation>
</message>
<message>
<source>Game can be completed with playable performance and no major glitches</source>
<translation>Game can be completed with playable performance and no major glitches</translation>
<translation>Gmożna ukończyć z grywalną wydajnością i bez większych usterek</translation>
</message>
</context>
<context>

View File

@ -58,4 +58,48 @@ Id EmitUnpackHalf2x16(EmitContext& ctx, Id value) {
return ctx.OpUnpackHalf2x16(ctx.F32[2], value);
}
Id EmitPackUnorm2x16(EmitContext& ctx, Id value) {
return ctx.OpPackUnorm2x16(ctx.U32[1], value);
}
Id EmitUnpackUnorm2x16(EmitContext& ctx, Id value) {
return ctx.OpUnpackUnorm2x16(ctx.F32[2], value);
}
Id EmitPackSnorm2x16(EmitContext& ctx, Id value) {
return ctx.OpPackSnorm2x16(ctx.U32[1], value);
}
Id EmitUnpackSnorm2x16(EmitContext& ctx, Id value) {
return ctx.OpUnpackSnorm2x16(ctx.F32[2], value);
}
Id EmitPackUint2x16(EmitContext& ctx, Id value) {
// No SPIR-V instruction for this, do it manually.
const auto x{ctx.OpCompositeExtract(ctx.U32[1], value, 0)};
const auto y{ctx.OpCompositeExtract(ctx.U32[1], value, 1)};
return ctx.OpBitFieldInsert(ctx.U32[1], x, y, ctx.ConstU32(16U), ctx.ConstU32(16U));
}
Id EmitUnpackUint2x16(EmitContext& ctx, Id value) {
// No SPIR-V instruction for this, do it manually.
const auto x{ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.ConstU32(0U), ctx.ConstU32(16U))};
const auto y{ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.ConstU32(16U), ctx.ConstU32(16U))};
return ctx.OpCompositeConstruct(ctx.U32[2], x, y);
}
Id EmitPackSint2x16(EmitContext& ctx, Id value) {
// No SPIR-V instruction for this, do it manually.
const auto x{ctx.OpCompositeExtract(ctx.U32[1], value, 0)};
const auto y{ctx.OpCompositeExtract(ctx.U32[1], value, 1)};
return ctx.OpBitFieldInsert(ctx.U32[1], x, y, ctx.ConstU32(16U), ctx.ConstU32(16U));
}
Id EmitUnpackSint2x16(EmitContext& ctx, Id value) {
// No SPIR-V instruction for this, do it manually.
const auto x{ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.ConstU32(0U), ctx.ConstU32(16U))};
const auto y{ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.ConstU32(16U), ctx.ConstU32(16U))};
return ctx.OpCompositeConstruct(ctx.U32[2], x, y);
}
} // namespace Shader::Backend::SPIRV

View File

@ -197,6 +197,14 @@ Id EmitPackFloat2x16(EmitContext& ctx, Id value);
Id EmitUnpackFloat2x16(EmitContext& ctx, Id value);
Id EmitPackHalf2x16(EmitContext& ctx, Id value);
Id EmitUnpackHalf2x16(EmitContext& ctx, Id value);
Id EmitPackUnorm2x16(EmitContext& ctx, Id value);
Id EmitUnpackUnorm2x16(EmitContext& ctx, Id value);
Id EmitPackSnorm2x16(EmitContext& ctx, Id value);
Id EmitUnpackSnorm2x16(EmitContext& ctx, Id value);
Id EmitPackUint2x16(EmitContext& ctx, Id value);
Id EmitUnpackUint2x16(EmitContext& ctx, Id value);
Id EmitPackSint2x16(EmitContext& ctx, Id value);
Id EmitUnpackSint2x16(EmitContext& ctx, Id value);
Id EmitFPAbs16(EmitContext& ctx, Id value);
Id EmitFPAbs32(EmitContext& ctx, Id value);
Id EmitFPAbs64(EmitContext& ctx, Id value);
@ -348,7 +356,8 @@ Id EmitSLessThanEqual(EmitContext& ctx, Id lhs, Id rhs);
Id EmitULessThanEqual(EmitContext& ctx, Id lhs, Id rhs);
Id EmitSGreaterThan(EmitContext& ctx, Id lhs, Id rhs);
Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs);
Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs);
Id EmitINotEqual32(EmitContext& ctx, Id lhs, Id rhs);
Id EmitINotEqual64(EmitContext& ctx, Id lhs, Id rhs);
Id EmitSGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
Id EmitUGreaterThanEqual(EmitContext& ctx, Id lhs, Id rhs);
Id EmitLogicalOr(EmitContext& ctx, Id a, Id b);

View File

@ -324,7 +324,11 @@ Id EmitUGreaterThan(EmitContext& ctx, Id lhs, Id rhs) {
return ctx.OpUGreaterThan(ctx.U1[1], lhs, rhs);
}
Id EmitINotEqual(EmitContext& ctx, Id lhs, Id rhs) {
Id EmitINotEqual32(EmitContext& ctx, Id lhs, Id rhs) {
return ctx.OpINotEqual(ctx.U1[1], lhs, rhs);
}
Id EmitINotEqual64(EmitContext& ctx, Id lhs, Id rhs) {
return ctx.OpINotEqual(ctx.U1[1], lhs, rhs);
}

View File

@ -7,6 +7,125 @@
namespace Shader::Gcn {
u32 SwizzleMrtComponent(const FragmentRuntimeInfo::PsColorBuffer& color_buffer, u32 comp) {
const auto [r, g, b, a] = color_buffer.swizzle;
const std::array swizzle_array = {r, g, b, a};
const auto swizzled_comp_type = static_cast<u32>(swizzle_array[comp]);
constexpr auto min_comp_type = static_cast<u32>(AmdGpu::CompSwizzle::Red);
return swizzled_comp_type >= min_comp_type ? swizzled_comp_type - min_comp_type : comp;
}
void Translator::ExportMrtValue(IR::Attribute attribute, u32 comp, const IR::F32& value,
const FragmentRuntimeInfo::PsColorBuffer& color_buffer) {
const auto converted = ApplyWriteNumberConversion(ir, value, color_buffer.num_conversion);
ir.SetAttribute(attribute, converted, comp);
}
void Translator::ExportMrtCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value) {
const u32 color_buffer_idx =
static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::RenderTarget0);
const auto color_buffer = runtime_info.fs_info.color_buffers[color_buffer_idx];
IR::Value unpacked_value;
bool is_integer = false;
switch (color_buffer.export_format) {
case AmdGpu::Liverpool::ShaderExportFormat::Zero:
// No export
return;
case AmdGpu::Liverpool::ShaderExportFormat::ABGR_FP16:
unpacked_value = ir.UnpackHalf2x16(value);
break;
case AmdGpu::Liverpool::ShaderExportFormat::ABGR_UNORM16:
unpacked_value = ir.UnpackUnorm2x16(value);
break;
case AmdGpu::Liverpool::ShaderExportFormat::ABGR_SNORM16:
unpacked_value = ir.UnpackSnorm2x16(value);
break;
case AmdGpu::Liverpool::ShaderExportFormat::ABGR_UINT16:
unpacked_value = ir.UnpackUint2x16(value);
is_integer = true;
break;
case AmdGpu::Liverpool::ShaderExportFormat::ABGR_SINT16:
unpacked_value = ir.UnpackSint2x16(value);
is_integer = true;
break;
default:
UNREACHABLE_MSG("Unimplemented compressed MRT export format {}",
static_cast<u32>(color_buffer.export_format));
break;
}
const auto r = ir.CompositeExtract(unpacked_value, 0);
const auto g = ir.CompositeExtract(unpacked_value, 1);
const IR::F32 float_r = is_integer ? ir.BitCast<IR::F32>(IR::U32{r}) : IR::F32{r};
const IR::F32 float_g = is_integer ? ir.BitCast<IR::F32>(IR::U32{g}) : IR::F32{g};
const auto swizzled_r = SwizzleMrtComponent(color_buffer, idx * 2);
const auto swizzled_g = SwizzleMrtComponent(color_buffer, idx * 2 + 1);
ExportMrtValue(attribute, swizzled_r, float_r, color_buffer);
ExportMrtValue(attribute, swizzled_g, float_g, color_buffer);
}
void Translator::ExportMrtUncompressed(IR::Attribute attribute, u32 comp, const IR::F32& value) {
const u32 color_buffer_idx =
static_cast<u32>(attribute) - static_cast<u32>(IR::Attribute::RenderTarget0);
const auto color_buffer = runtime_info.fs_info.color_buffers[color_buffer_idx];
const auto swizzled_comp = SwizzleMrtComponent(color_buffer, comp);
switch (color_buffer.export_format) {
case AmdGpu::Liverpool::ShaderExportFormat::Zero:
// No export
return;
case AmdGpu::Liverpool::ShaderExportFormat::R_32:
// Red only
if (swizzled_comp != 0) {
return;
}
break;
case AmdGpu::Liverpool::ShaderExportFormat::GR_32:
// Red and Green only
if (swizzled_comp != 0 && swizzled_comp != 1) {
return;
}
break;
case AmdGpu::Liverpool::ShaderExportFormat::AR_32:
// Red and Alpha only
if (swizzled_comp != 0 && swizzled_comp != 3) {
return;
}
break;
case AmdGpu::Liverpool::ShaderExportFormat::ABGR_32:
// All components
break;
default:
UNREACHABLE_MSG("Unimplemented uncompressed MRT export format {}",
static_cast<u32>(color_buffer.export_format));
break;
}
ExportMrtValue(attribute, swizzled_comp, value, color_buffer);
}
void Translator::ExportCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value) {
if (IsMrt(attribute)) {
ExportMrtCompressed(attribute, idx, value);
return;
}
const IR::Value unpacked_value = ir.UnpackHalf2x16(value);
const IR::F32 r = IR::F32{ir.CompositeExtract(unpacked_value, 0)};
const IR::F32 g = IR::F32{ir.CompositeExtract(unpacked_value, 1)};
ir.SetAttribute(attribute, r, idx * 2);
ir.SetAttribute(attribute, g, idx * 2 + 1);
}
void Translator::ExportUncompressed(IR::Attribute attribute, u32 comp, const IR::F32& value) {
if (IsMrt(attribute)) {
ExportMrtUncompressed(attribute, comp, value);
return;
}
ir.SetAttribute(attribute, value, comp);
}
void Translator::EmitExport(const GcnInst& inst) {
if (ir.block->has_multiple_predecessors && info.stage == Stage::Fragment) {
ir.Discard(ir.LogicalNot(ir.GetExec()));
@ -26,41 +145,15 @@ void Translator::EmitExport(const GcnInst& inst) {
IR::VectorReg(inst.src[3].code),
};
const auto set_attribute = [&](u32 comp, IR::F32 value) {
if (!IR::IsMrt(attrib)) {
ir.SetAttribute(attrib, value, comp);
return;
}
const u32 index = u32(attrib) - u32(IR::Attribute::RenderTarget0);
const auto col_buf = runtime_info.fs_info.color_buffers[index];
const auto converted = IR::ApplyWriteNumberConversion(ir, value, col_buf.num_conversion);
const auto [r, g, b, a] = col_buf.swizzle;
const std::array swizzle_array = {r, g, b, a};
const auto swizzled_comp = swizzle_array[comp];
if (u32(swizzled_comp) < u32(AmdGpu::CompSwizzle::Red)) {
ir.SetAttribute(attrib, converted, comp);
return;
}
ir.SetAttribute(attrib, converted, u32(swizzled_comp) - u32(AmdGpu::CompSwizzle::Red));
};
const auto unpack = [&](u32 idx) {
const IR::Value value = ir.UnpackHalf2x16(ir.GetVectorReg(vsrc[idx]));
const IR::F32 r = IR::F32{ir.CompositeExtract(value, 0)};
const IR::F32 g = IR::F32{ir.CompositeExtract(value, 1)};
set_attribute(idx * 2, r);
set_attribute(idx * 2 + 1, g);
};
// Components are float16 packed into a VGPR
if (exp.compr) {
// Export R, G
if (exp.en & 1) {
unpack(0);
ExportCompressed(attrib, 0, ir.GetVectorReg<IR::U32>(vsrc[0]));
}
// Export B, A
if ((exp.en >> 2) & 1) {
unpack(1);
ExportCompressed(attrib, 1, ir.GetVectorReg<IR::U32>(vsrc[1]));
}
} else {
// Components are float32 into separate VGPRS
@ -69,8 +162,7 @@ void Translator::EmitExport(const GcnInst& inst) {
if ((mask & 1) == 0) {
continue;
}
const IR::F32 comp = ir.GetVectorReg<IR::F32>(vsrc[i]);
set_attribute(i, comp);
ExportUncompressed(attrib, i, ir.GetVectorReg<IR::F32>(vsrc[i]));
}
}
if (IR::IsMrt(attrib)) {

View File

@ -72,10 +72,14 @@ void Translator::EmitScalarAlu(const GcnInst& inst) {
return S_OR_B64(NegateMode::Result, true, inst);
case Opcode::S_LSHL_B32:
return S_LSHL_B32(inst);
case Opcode::S_LSHL_B64:
return S_LSHL_B64(inst);
case Opcode::S_LSHR_B32:
return S_LSHR_B32(inst);
case Opcode::S_ASHR_I32:
return S_ASHR_I32(inst);
case Opcode::S_ASHR_I64:
return S_ASHR_I64(inst);
case Opcode::S_BFM_B32:
return S_BFM_B32(inst);
case Opcode::S_MUL_I32:
@ -420,6 +424,14 @@ void Translator::S_LSHL_B32(const GcnInst& inst) {
ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
}
void Translator::S_LSHL_B64(const GcnInst& inst) {
const IR::U64 src0{GetSrc64(inst.src[0])};
const IR::U64 src1{GetSrc64(inst.src[1])};
const IR::U64 result = ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))));
SetDst64(inst.dst[0], result);
ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0))));
}
void Translator::S_LSHR_B32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
@ -431,11 +443,19 @@ void Translator::S_LSHR_B32(const GcnInst& inst) {
void Translator::S_ASHR_I32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 result{ir.ShiftRightArithmetic(src0, src1)};
const IR::U32 result{ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm32(0x1F)))};
SetDst(inst.dst[0], result);
ir.SetScc(ir.INotEqual(result, ir.Imm32(0)));
}
void Translator::S_ASHR_I64(const GcnInst& inst) {
const IR::U64 src0{GetSrc64(inst.src[0])};
const IR::U64 src1{GetSrc64(inst.src[1])};
const IR::U64 result{ir.ShiftRightArithmetic(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F))))};
SetDst64(inst.dst[0], result);
ir.SetScc(ir.INotEqual(result, ir.Imm64(u64(0))));
}
void Translator::S_BFM_B32(const GcnInst& inst) {
const IR::U32 src0{ir.BitwiseAnd(GetSrc(inst.src[0]), ir.Imm32(0x1F))};
const IR::U32 src1{ir.BitwiseAnd(GetSrc(inst.src[1]), ir.Imm32(0x1F))};

View File

@ -90,8 +90,10 @@ public:
void S_OR_B64(NegateMode negate, bool is_xor, const GcnInst& inst);
void S_XOR_B32(const GcnInst& inst);
void S_LSHL_B32(const GcnInst& inst);
void S_LSHL_B64(const GcnInst& inst);
void S_LSHR_B32(const GcnInst& inst);
void S_ASHR_I32(const GcnInst& inst);
void S_ASHR_I64(const GcnInst& inst);
void S_BFM_B32(const GcnInst& inst);
void S_MUL_I32(const GcnInst& inst);
void S_BFE(const GcnInst& inst, bool is_signed);
@ -168,6 +170,7 @@ public:
void V_SUBBREV_U32(const GcnInst& inst);
void V_LDEXP_F32(const GcnInst& inst);
void V_CVT_PKNORM_U16_F32(const GcnInst& inst);
void V_CVT_PKNORM_I16_F32(const GcnInst& inst);
void V_CVT_PKRTZ_F16_F32(const GcnInst& inst);
// VOP1
@ -242,6 +245,7 @@ public:
void V_SAD(const GcnInst& inst);
void V_SAD_U32(const GcnInst& inst);
void V_CVT_PK_U16_U32(const GcnInst& inst);
void V_CVT_PK_I16_I32(const GcnInst& inst);
void V_CVT_PK_U8_F32(const GcnInst& inst);
void V_LSHL_B64(const GcnInst& inst);
void V_MUL_F64(const GcnInst& inst);
@ -304,6 +308,13 @@ private:
IR::F32 SelectCubeResult(const IR::F32& x, const IR::F32& y, const IR::F32& z,
const IR::F32& x_res, const IR::F32& y_res, const IR::F32& z_res);
void ExportMrtValue(IR::Attribute attribute, u32 comp, const IR::F32& value,
const FragmentRuntimeInfo::PsColorBuffer& color_buffer);
void ExportMrtCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value);
void ExportMrtUncompressed(IR::Attribute attribute, u32 comp, const IR::F32& value);
void ExportCompressed(IR::Attribute attribute, u32 idx, const IR::U32& value);
void ExportUncompressed(IR::Attribute attribute, u32 comp, const IR::F32& value);
void LogMissingOpcode(const GcnInst& inst);
private:

View File

@ -96,6 +96,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) {
return V_LDEXP_F32(inst);
case Opcode::V_CVT_PKNORM_U16_F32:
return V_CVT_PKNORM_U16_F32(inst);
case Opcode::V_CVT_PKNORM_I16_F32:
return V_CVT_PKNORM_I16_F32(inst);
case Opcode::V_CVT_PKRTZ_F16_F32:
return V_CVT_PKRTZ_F16_F32(inst);
@ -376,6 +378,8 @@ void Translator::EmitVectorAlu(const GcnInst& inst) {
return V_SAD_U32(inst);
case Opcode::V_CVT_PK_U16_U32:
return V_CVT_PK_U16_U32(inst);
case Opcode::V_CVT_PK_I16_I32:
return V_CVT_PK_I16_I32(inst);
case Opcode::V_CVT_PK_U8_F32:
return V_CVT_PK_U8_F32(inst);
case Opcode::V_LSHL_B64:
@ -645,12 +649,15 @@ void Translator::V_LDEXP_F32(const GcnInst& inst) {
}
void Translator::V_CVT_PKNORM_U16_F32(const GcnInst& inst) {
const IR::F32 src0{GetSrc<IR::F32>(inst.src[0])};
const IR::F32 src1{GetSrc<IR::F32>(inst.src[1])};
const IR::U32 dst0 = ir.ConvertFToU(32, ir.FPMul(src0, ir.Imm32(65535.f)));
const IR::U32 dst1 = ir.ConvertFToU(32, ir.FPMul(src1, ir.Imm32(65535.f)));
const IR::VectorReg dst_reg{inst.dst[0].code};
ir.SetVectorReg(dst_reg, ir.BitFieldInsert(dst0, dst1, ir.Imm32(16), ir.Imm32(16)));
const IR::Value vec_f32 =
ir.CompositeConstruct(GetSrc<IR::F32>(inst.src[0]), GetSrc<IR::F32>(inst.src[1]));
SetDst(inst.dst[0], ir.PackUnorm2x16(vec_f32));
}
void Translator::V_CVT_PKNORM_I16_F32(const GcnInst& inst) {
const IR::Value vec_f32 =
ir.CompositeConstruct(GetSrc<IR::F32>(inst.src[0]), GetSrc<IR::F32>(inst.src[1]));
SetDst(inst.dst[0], ir.PackSnorm2x16(vec_f32));
}
void Translator::V_CVT_PKRTZ_F16_F32(const GcnInst& inst) {
@ -1237,11 +1244,15 @@ void Translator::V_SAD_U32(const GcnInst& inst) {
}
void Translator::V_CVT_PK_U16_U32(const GcnInst& inst) {
const IR::U32 src0{GetSrc(inst.src[0])};
const IR::U32 src1{GetSrc(inst.src[1])};
const IR::U32 lo = ir.IMin(src0, ir.Imm32(0xFFFF), false);
const IR::U32 hi = ir.IMin(src1, ir.Imm32(0xFFFF), false);
SetDst(inst.dst[0], ir.BitFieldInsert(lo, hi, ir.Imm32(16), ir.Imm32(16)));
const IR::Value vec_u32 =
ir.CompositeConstruct(GetSrc<IR::U32>(inst.src[0]), GetSrc<IR::U32>(inst.src[1]));
SetDst(inst.dst[0], ir.PackUint2x16(vec_u32));
}
void Translator::V_CVT_PK_I16_I32(const GcnInst& inst) {
const IR::Value vec_u32 =
ir.CompositeConstruct(GetSrc<IR::U32>(inst.src[0]), GetSrc<IR::U32>(inst.src[1]));
SetDst(inst.dst[0], ir.PackSint2x16(vec_u32));
}
void Translator::V_CVT_PK_U8_F32(const GcnInst& inst) {
@ -1257,24 +1268,7 @@ void Translator::V_CVT_PK_U8_F32(const GcnInst& inst) {
void Translator::V_LSHL_B64(const GcnInst& inst) {
const IR::U64 src0{GetSrc64(inst.src[0])};
const IR::U64 src1{GetSrc64(inst.src[1])};
const IR::VectorReg dst_reg{inst.dst[0].code};
if (src0.IsImmediate()) {
if (src0.U64() == -1) {
// If src0 is a fixed -1, the result will always be -1.
ir.SetVectorReg(dst_reg, ir.Imm32(0xFFFFFFFF));
ir.SetVectorReg(dst_reg + 1, ir.Imm32(0xFFFFFFFF));
return;
}
if (src1.IsImmediate()) {
// If both src0 and src1 are immediates, we can calculate the result now.
// Note that according to the manual, only bits 4:0 are used from src1.
const u64 result = src0.U64() << (src1.U64() & 0x1F);
ir.SetVectorReg(dst_reg, ir.Imm32(static_cast<u32>(result)));
ir.SetVectorReg(dst_reg + 1, ir.Imm32(static_cast<u32>(result >> 32)));
return;
}
}
UNREACHABLE_MSG("Unimplemented V_LSHL_B64 arguments");
SetDst64(inst.dst[0], ir.ShiftLeftLogical(src0, ir.BitwiseAnd(src1, ir.Imm64(u64(0x3F)))));
}
void Translator::V_MUL_F64(const GcnInst& inst) {

View File

@ -795,6 +795,38 @@ Value IREmitter::UnpackHalf2x16(const U32& value) {
return Inst(Opcode::UnpackHalf2x16, value);
}
U32 IREmitter::PackUnorm2x16(const Value& vector) {
return Inst<U32>(Opcode::PackUnorm2x16, vector);
}
Value IREmitter::UnpackUnorm2x16(const U32& value) {
return Inst(Opcode::UnpackUnorm2x16, value);
}
U32 IREmitter::PackSnorm2x16(const Value& vector) {
return Inst<U32>(Opcode::PackSnorm2x16, vector);
}
Value IREmitter::UnpackSnorm2x16(const U32& value) {
return Inst(Opcode::UnpackSnorm2x16, value);
}
U32 IREmitter::PackUint2x16(const Value& value) {
return Inst<U32>(Opcode::PackUint2x16, value);
}
Value IREmitter::UnpackUint2x16(const U32& value) {
return Inst(Opcode::UnpackUint2x16, value);
}
U32 IREmitter::PackSint2x16(const Value& value) {
return Inst<U32>(Opcode::PackSint2x16, value);
}
Value IREmitter::UnpackSint2x16(const U32& value) {
return Inst(Opcode::UnpackSint2x16, value);
}
F32F64 IREmitter::FPMul(const F32F64& a, const F32F64& b) {
if (a.Type() != b.Type()) {
UNREACHABLE_MSG("Mismatching types {} and {}", a.Type(), b.Type());
@ -1461,8 +1493,18 @@ U1 IREmitter::IGreaterThan(const U32& lhs, const U32& rhs, bool is_signed) {
return Inst<U1>(is_signed ? Opcode::SGreaterThan : Opcode::UGreaterThan, lhs, rhs);
}
U1 IREmitter::INotEqual(const U32& lhs, const U32& rhs) {
return Inst<U1>(Opcode::INotEqual, lhs, rhs);
U1 IREmitter::INotEqual(const U32U64& lhs, const U32U64& rhs) {
if (lhs.Type() != rhs.Type()) {
UNREACHABLE_MSG("Mismatching types {} and {}", lhs.Type(), rhs.Type());
}
switch (lhs.Type()) {
case Type::U32:
return Inst<U1>(Opcode::INotEqual32, lhs, rhs);
case Type::U64:
return Inst<U1>(Opcode::INotEqual64, lhs, rhs);
default:
ThrowInvalidType(lhs.Type());
}
}
U1 IREmitter::IGreaterThanEqual(const U32& lhs, const U32& rhs, bool is_signed) {

View File

@ -175,6 +175,14 @@ public:
[[nodiscard]] U32 PackHalf2x16(const Value& vector);
[[nodiscard]] Value UnpackHalf2x16(const U32& value);
[[nodiscard]] U32 PackUnorm2x16(const Value& vector);
[[nodiscard]] Value UnpackUnorm2x16(const U32& value);
[[nodiscard]] U32 PackSnorm2x16(const Value& vector);
[[nodiscard]] Value UnpackSnorm2x16(const U32& value);
[[nodiscard]] U32 PackUint2x16(const Value& value);
[[nodiscard]] Value UnpackUint2x16(const U32& value);
[[nodiscard]] U32 PackSint2x16(const Value& value);
[[nodiscard]] Value UnpackSint2x16(const U32& value);
[[nodiscard]] F32F64 FPAdd(const F32F64& a, const F32F64& b);
[[nodiscard]] F32F64 FPSub(const F32F64& a, const F32F64& b);
@ -258,7 +266,7 @@ public:
[[nodiscard]] U1 IEqual(const U32U64& lhs, const U32U64& rhs);
[[nodiscard]] U1 ILessThanEqual(const U32& lhs, const U32& rhs, bool is_signed);
[[nodiscard]] U1 IGreaterThan(const U32& lhs, const U32& rhs, bool is_signed);
[[nodiscard]] U1 INotEqual(const U32& lhs, const U32& rhs);
[[nodiscard]] U1 INotEqual(const U32U64& lhs, const U32U64& rhs);
[[nodiscard]] U1 IGreaterThanEqual(const U32& lhs, const U32& rhs, bool is_signed);
[[nodiscard]] U1 LogicalOr(const U1& a, const U1& b);

View File

@ -187,6 +187,14 @@ OPCODE(PackFloat2x16, U32, F16x
OPCODE(UnpackFloat2x16, F16x2, U32, )
OPCODE(PackHalf2x16, U32, F32x2, )
OPCODE(UnpackHalf2x16, F32x2, U32, )
OPCODE(PackUnorm2x16, U32, F32x2, )
OPCODE(UnpackUnorm2x16, F32x2, U32, )
OPCODE(PackSnorm2x16, U32, F32x2, )
OPCODE(UnpackSnorm2x16, F32x2, U32, )
OPCODE(PackUint2x16, U32, U32x2, )
OPCODE(UnpackUint2x16, U32x2, U32, )
OPCODE(PackSint2x16, U32, U32x2, )
OPCODE(UnpackSint2x16, U32x2, U32, )
// Floating-point operations
OPCODE(FPAbs32, F32, F32, )
@ -321,7 +329,8 @@ OPCODE(SLessThanEqual, U1, U32,
OPCODE(ULessThanEqual, U1, U32, U32, )
OPCODE(SGreaterThan, U1, U32, U32, )
OPCODE(UGreaterThan, U1, U32, U32, )
OPCODE(INotEqual, U1, U32, U32, )
OPCODE(INotEqual32, U1, U32, U32, )
OPCODE(INotEqual64, U1, U64, U64, )
OPCODE(SGreaterThanEqual, U1, U32, U32, )
OPCODE(UGreaterThanEqual, U1, U32, U32, )

View File

@ -348,6 +348,22 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
return FoldInverseFunc(inst, IR::Opcode::UnpackFloat2x16);
case IR::Opcode::UnpackFloat2x16:
return FoldInverseFunc(inst, IR::Opcode::PackFloat2x16);
case IR::Opcode::PackUnorm2x16:
return FoldInverseFunc(inst, IR::Opcode::UnpackUnorm2x16);
case IR::Opcode::UnpackUnorm2x16:
return FoldInverseFunc(inst, IR::Opcode::PackUnorm2x16);
case IR::Opcode::PackSnorm2x16:
return FoldInverseFunc(inst, IR::Opcode::UnpackSnorm2x16);
case IR::Opcode::UnpackSnorm2x16:
return FoldInverseFunc(inst, IR::Opcode::PackSnorm2x16);
case IR::Opcode::PackUint2x16:
return FoldInverseFunc(inst, IR::Opcode::UnpackUint2x16);
case IR::Opcode::UnpackUint2x16:
return FoldInverseFunc(inst, IR::Opcode::PackUint2x16);
case IR::Opcode::PackSint2x16:
return FoldInverseFunc(inst, IR::Opcode::UnpackSint2x16);
case IR::Opcode::UnpackSint2x16:
return FoldInverseFunc(inst, IR::Opcode::PackSint2x16);
case IR::Opcode::SelectU1:
case IR::Opcode::SelectU8:
case IR::Opcode::SelectU16:
@ -403,9 +419,12 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
case IR::Opcode::IEqual64:
FoldWhenAllImmediates(inst, [](u64 a, u64 b) { return a == b; });
return;
case IR::Opcode::INotEqual:
case IR::Opcode::INotEqual32:
FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a != b; });
return;
case IR::Opcode::INotEqual64:
FoldWhenAllImmediates(inst, [](u64 a, u64 b) { return a != b; });
return;
case IR::Opcode::BitwiseAnd32:
FoldWhenAllImmediates(inst, [](u32 a, u32 b) { return a & b; });
return;

View File

@ -569,7 +569,7 @@ void PatchTextureBufferArgs(IR::Block& block, IR::Inst& inst, Info& info) {
inst.SetArg(1, CalculateBufferAddress(ir, inst, info, buffer, 1U));
if (inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32) {
const auto swizzled = ApplySwizzle(ir, inst.Arg(2), buffer.DstSelect());
const auto swizzled = ApplySwizzle(ir, inst.Arg(2), buffer.DstSelect().Inverse());
const auto converted =
ApplyWriteNumberConversionVec4(ir, swizzled, buffer.GetNumberConversion());
inst.SetArg(2, converted);
@ -829,7 +829,7 @@ void PatchImageArgs(IR::Block& block, IR::Inst& inst, Info& info) {
auto texel = inst.Arg(4);
if (is_storage) {
// Storage image requires shader swizzle.
texel = ApplySwizzle(ir, texel, image.DstSelect());
texel = ApplySwizzle(ir, texel, image.DstSelect().Inverse());
}
const auto converted =
ApplyWriteNumberConversionVec4(ir, texel, image.GetNumberConversion());

View File

@ -184,6 +184,7 @@ struct FragmentRuntimeInfo {
AmdGpu::NumberFormat num_format;
AmdGpu::NumberConversion num_conversion;
AmdGpu::CompMapping swizzle;
AmdGpu::Liverpool::ShaderExportFormat export_format;
auto operator<=>(const PsColorBuffer&) const noexcept = default;
};

View File

@ -266,6 +266,10 @@ struct Liverpool {
BitField<20, 4, ShaderExportFormat> col5;
BitField<24, 4, ShaderExportFormat> col6;
BitField<28, 4, ShaderExportFormat> col7;
[[nodiscard]] ShaderExportFormat GetFormat(const u32 buf_idx) const {
return static_cast<ShaderExportFormat>((raw >> (buf_idx * 4)) & 0xfu);
}
};
union VsOutputControl {
@ -904,7 +908,7 @@ struct Liverpool {
}
bool IsTiled() const {
return !info.linear_general;
return GetTilingMode() != TilingMode::Display_Linear;
}
[[nodiscard]] DataFormat GetDataFmt() const {

View File

@ -200,10 +200,10 @@ enum class NumberConversion : u32 {
};
struct CompMapping {
CompSwizzle r : 3;
CompSwizzle g : 3;
CompSwizzle b : 3;
CompSwizzle a : 3;
CompSwizzle r;
CompSwizzle g;
CompSwizzle b;
CompSwizzle a;
auto operator<=>(const CompMapping& other) const = default;
@ -217,6 +217,15 @@ struct CompMapping {
};
}
[[nodiscard]] CompMapping Inverse() const {
CompMapping result{};
InverseSingle(result.r, CompSwizzle::Red);
InverseSingle(result.g, CompSwizzle::Green);
InverseSingle(result.b, CompSwizzle::Blue);
InverseSingle(result.a, CompSwizzle::Alpha);
return result;
}
private:
template <typename T>
T ApplySingle(const std::array<T, 4>& data, const CompSwizzle swizzle) const {
@ -237,6 +246,20 @@ private:
UNREACHABLE();
}
}
void InverseSingle(CompSwizzle& dst, const CompSwizzle target) const {
if (r == target) {
dst = CompSwizzle::Red;
} else if (g == target) {
dst = CompSwizzle::Green;
} else if (b == target) {
dst = CompSwizzle::Blue;
} else if (a == target) {
dst = CompSwizzle::Alpha;
} else {
dst = CompSwizzle::Zero;
}
}
};
inline DataFormat RemapDataFormat(const DataFormat format) {

View File

@ -1,108 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "video_core/renderer_vulkan/vk_descriptor_update_queue.h"
#include "video_core/renderer_vulkan/vk_instance.h"
namespace Vulkan {
DescriptorUpdateQueue::DescriptorUpdateQueue(const Instance& instance, u32 descriptor_write_max_)
: device{instance.GetDevice()}, descriptor_write_max{descriptor_write_max_} {
descriptor_infos = std::make_unique<DescriptorInfoUnion[]>(descriptor_write_max);
descriptor_writes = std::make_unique<vk::WriteDescriptorSet[]>(descriptor_write_max);
}
void DescriptorUpdateQueue::Flush() {
if (descriptor_write_end == 0) {
return;
}
device.updateDescriptorSets({std::span(descriptor_writes.get(), descriptor_write_end)}, {});
descriptor_write_end = 0;
}
void DescriptorUpdateQueue::AddStorageImage(vk::DescriptorSet target, u8 binding,
vk::ImageView image_view,
vk::ImageLayout image_layout) {
if (descriptor_write_end >= descriptor_write_max) [[unlikely]] {
Flush();
}
auto& image_info = descriptor_infos[descriptor_write_end].image_info;
image_info.sampler = VK_NULL_HANDLE;
image_info.imageView = image_view;
image_info.imageLayout = image_layout;
descriptor_writes[descriptor_write_end++] = vk::WriteDescriptorSet{
.dstSet = target,
.dstBinding = binding,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eStorageImage,
.pImageInfo = &image_info,
};
}
void DescriptorUpdateQueue::AddImageSampler(vk::DescriptorSet target, u8 binding, u8 array_index,
vk::ImageView image_view, vk::Sampler sampler,
vk::ImageLayout image_layout) {
if (descriptor_write_end >= descriptor_write_max) [[unlikely]] {
Flush();
}
auto& image_info = descriptor_infos[descriptor_write_end].image_info;
image_info.sampler = sampler;
image_info.imageView = image_view;
image_info.imageLayout = image_layout;
descriptor_writes[descriptor_write_end++] = vk::WriteDescriptorSet{
.dstSet = target,
.dstBinding = binding,
.dstArrayElement = array_index,
.descriptorCount = 1,
.descriptorType =
sampler ? vk::DescriptorType::eCombinedImageSampler : vk::DescriptorType::eSampledImage,
.pImageInfo = &image_info,
};
}
void DescriptorUpdateQueue::AddBuffer(vk::DescriptorSet target, u8 binding, vk::Buffer buffer,
vk::DeviceSize offset, vk::DeviceSize size,
vk::DescriptorType type) {
if (descriptor_write_end >= descriptor_write_max) [[unlikely]] {
Flush();
}
auto& buffer_info = descriptor_infos[descriptor_write_end].buffer_info;
buffer_info.buffer = buffer;
buffer_info.offset = offset;
buffer_info.range = size;
descriptor_writes[descriptor_write_end++] = vk::WriteDescriptorSet{
.dstSet = target,
.dstBinding = binding,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = type,
.pBufferInfo = &buffer_info,
};
}
void DescriptorUpdateQueue::AddTexelBuffer(vk::DescriptorSet target, u8 binding,
vk::BufferView buffer_view) {
if (descriptor_write_end >= descriptor_write_max) [[unlikely]] {
Flush();
}
auto& buffer_info = descriptor_infos[descriptor_write_end].buffer_view;
buffer_info = buffer_view;
descriptor_writes[descriptor_write_end++] = vk::WriteDescriptorSet{
.dstSet = target,
.dstBinding = binding,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = vk::DescriptorType::eUniformTexelBuffer,
.pTexelBufferView = &buffer_info,
};
}
} // namespace Vulkan

View File

@ -1,51 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
#include "common/types.h"
#include "video_core/renderer_vulkan/vk_common.h"
namespace Vulkan {
class Instance;
struct DescriptorInfoUnion {
DescriptorInfoUnion() {}
union {
vk::DescriptorImageInfo image_info;
vk::DescriptorBufferInfo buffer_info;
vk::BufferView buffer_view;
};
};
class DescriptorUpdateQueue {
public:
explicit DescriptorUpdateQueue(const Instance& instance, u32 descriptor_write_max = 2048);
~DescriptorUpdateQueue() = default;
void Flush();
void AddStorageImage(vk::DescriptorSet target, u8 binding, vk::ImageView image_view,
vk::ImageLayout image_layout = vk::ImageLayout::eGeneral);
void AddImageSampler(vk::DescriptorSet target, u8 binding, u8 array_index,
vk::ImageView image_view, vk::Sampler sampler,
vk::ImageLayout imageLayout = vk::ImageLayout::eGeneral);
void AddBuffer(vk::DescriptorSet target, u8 binding, vk::Buffer buffer, vk::DeviceSize offset,
vk::DeviceSize size = VK_WHOLE_SIZE,
vk::DescriptorType type = vk::DescriptorType::eUniformBufferDynamic);
void AddTexelBuffer(vk::DescriptorSet target, u8 binding, vk::BufferView buffer_view);
private:
const vk::Device device;
const u32 descriptor_write_max;
std::unique_ptr<DescriptorInfoUnion[]> descriptor_infos;
std::unique_ptr<vk::WriteDescriptorSet[]> descriptor_writes;
u32 descriptor_write_end = 0;
};
} // namespace Vulkan

View File

@ -35,9 +35,8 @@ struct GraphicsPipelineKey {
std::array<size_t, MaxShaderStages> stage_hashes;
u32 num_color_attachments;
std::array<vk::Format, Liverpool::NumColorBuffers> color_formats;
std::array<AmdGpu::NumberFormat, Liverpool::NumColorBuffers> color_num_formats;
std::array<AmdGpu::NumberConversion, Liverpool::NumColorBuffers> color_num_conversions;
std::array<AmdGpu::CompMapping, Liverpool::NumColorBuffers> color_swizzles;
std::array<Shader::FragmentRuntimeInfo::PsColorBuffer, Liverpool::NumColorBuffers>
color_buffers;
vk::Format depth_format;
vk::Format stencil_format;

View File

@ -167,11 +167,7 @@ const Shader::RuntimeInfo& PipelineCache::BuildRuntimeInfo(Stage stage, LogicalS
};
}
for (u32 i = 0; i < Shader::MaxColorBuffers; i++) {
info.fs_info.color_buffers[i] = {
.num_format = graphics_key.color_num_formats[i],
.num_conversion = graphics_key.color_num_conversions[i],
.swizzle = graphics_key.color_swizzles[i],
};
info.fs_info.color_buffers[i] = graphics_key.color_buffers[i];
}
break;
}
@ -309,11 +305,9 @@ bool PipelineCache::RefreshGraphicsKey() {
// order. We need to do some arrays compaction at this stage
key.num_color_attachments = 0;
key.color_formats.fill(vk::Format::eUndefined);
key.color_num_formats.fill(AmdGpu::NumberFormat::Unorm);
key.color_num_conversions.fill(AmdGpu::NumberConversion::None);
key.color_buffers.fill({});
key.blend_controls.fill({});
key.write_masks.fill({});
key.color_swizzles.fill({});
key.vertex_buffer_formats.fill(vk::Format::eUndefined);
key.patch_control_points = 0;
@ -338,9 +332,12 @@ bool PipelineCache::RefreshGraphicsKey() {
key.color_formats[remapped_cb] =
LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt());
key.color_num_formats[remapped_cb] = col_buf.GetNumberFmt();
key.color_num_conversions[remapped_cb] = col_buf.GetNumberConversion();
key.color_swizzles[remapped_cb] = col_buf.Swizzle();
key.color_buffers[remapped_cb] = {
.num_format = col_buf.GetNumberFmt(),
.num_conversion = col_buf.GetNumberConversion(),
.swizzle = col_buf.Swizzle(),
.export_format = regs.color_export_format.GetFormat(cb),
};
}
fetch_shader = std::nullopt;
@ -456,7 +453,7 @@ bool PipelineCache::RefreshGraphicsKey() {
// of the latter we need to change format to undefined, and either way we need to
// increment the index for the null attachment binding.
key.color_formats[remapped_cb] = vk::Format::eUndefined;
key.color_swizzles[remapped_cb] = {};
key.color_buffers[remapped_cb] = {};
++remapped_cb;
continue;
}

View File

@ -345,8 +345,13 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) {
view_slice = -1;
const auto& merged_info = image_id ? slot_images[image_id].info : info;
std::tie(image_id, view_mip, view_slice) =
auto [overlap_image_id, overlap_view_mip, overlap_view_slice] =
ResolveOverlap(merged_info, desc.type, cache_id, image_id);
if (overlap_image_id) {
image_id = overlap_image_id;
view_mip = overlap_view_mip;
view_slice = overlap_view_slice;
}
}
}