From 134541bdcd79a6e1c223a7ed2c0eecca6d870272 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 5 Jul 2024 15:08:33 +0300 Subject: [PATCH 01/20] submodules updates --- externals/fmt | 2 +- externals/glslang | 2 +- externals/magic_enum | 2 +- externals/sdl3 | 2 +- externals/vma | 2 +- externals/zlib-ng | 2 +- src/sdl_window.cpp | 28 ++++++++++++++-------------- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/externals/fmt b/externals/fmt index bbf44cc00..a96259701 160000 --- a/externals/fmt +++ b/externals/fmt @@ -1 +1 @@ -Subproject commit bbf44cc000531dc7737d5321ccfa9f2f11b20127 +Subproject commit a96259701e1d16e2f8c8299c668e863ec0ac0119 diff --git a/externals/glslang b/externals/glslang index 33c7e3086..5939e32b8 160000 --- a/externals/glslang +++ b/externals/glslang @@ -1 +1 @@ -Subproject commit 33c7e30860928bab3819c3abae8297b109a02f73 +Subproject commit 5939e32b87487fa9c72ab336ebfcc5ae26d9ab6d diff --git a/externals/magic_enum b/externals/magic_enum index dd6a39d0b..ec1adc576 160000 --- a/externals/magic_enum +++ b/externals/magic_enum @@ -1 +1 @@ -Subproject commit dd6a39d0ba1852cf06907e0f0573a2a10d23c2ad +Subproject commit ec1adc5763f684e0f32888b157bfc0b86021b8e9 diff --git a/externals/sdl3 b/externals/sdl3 index b72c22340..f9a06c20e 160000 --- a/externals/sdl3 +++ b/externals/sdl3 @@ -1 +1 @@ -Subproject commit b72c22340e9a3c680011e245c28492bf60f5be66 +Subproject commit f9a06c20ed85fb1d6754fc2280d6183382217910 diff --git a/externals/vma b/externals/vma index feb11e172..257138b8f 160000 --- a/externals/vma +++ b/externals/vma @@ -1 +1 @@ -Subproject commit feb11e172715011ef2a7b3b6c7c8737337b34181 +Subproject commit 257138b8f5686ae84491a3df9f90a77d5660c3bd diff --git a/externals/zlib-ng b/externals/zlib-ng index 80514c17b..d54e3769b 160000 --- a/externals/zlib-ng +++ b/externals/zlib-ng @@ -1 +1 @@ -Subproject commit 80514c17b384df68fbe83cca69ece0521b85f708 +Subproject commit d54e3769be0c522015b784eca2af258b1c026107 diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index 1cc3f65a3..d4da268af 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -130,7 +130,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { case SDLK_RETURN: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_OPTIONS; break; - case SDLK_a: + case SDLK_A: axis = Input::Axis::LeftX; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += -127; @@ -139,7 +139,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_d: + case SDLK_D: axis = Input::Axis::LeftX; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += 127; @@ -148,7 +148,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_w: + case SDLK_W: axis = Input::Axis::LeftY; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += -127; @@ -157,7 +157,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_s: + case SDLK_S: axis = Input::Axis::LeftY; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += 127; @@ -166,7 +166,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_j: + case SDLK_J: axis = Input::Axis::RightX; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += -127; @@ -175,7 +175,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_l: + case SDLK_L: axis = Input::Axis::RightX; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += 127; @@ -184,7 +184,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_i: + case SDLK_I: axis = Input::Axis::RightY; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += -127; @@ -193,7 +193,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_k: + case SDLK_K: axis = Input::Axis::RightY; if (event->type == SDL_EVENT_KEY_DOWN) { axisvalue += 127; @@ -202,19 +202,19 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(-0x80, 0x80, axisvalue); break; - case SDLK_x: + case SDLK_X: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L3; break; - case SDLK_m: + case SDLK_M: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R3; break; - case SDLK_q: + case SDLK_Q: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L1; break; - case SDLK_u: + case SDLK_U: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R1; break; - case SDLK_e: + case SDLK_E: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_L2; axis = Input::Axis::TriggerLeft; if (event->type == SDL_EVENT_KEY_DOWN) { @@ -224,7 +224,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) { } ax = Input::GetAxis(0, 0x80, axisvalue); break; - case SDLK_o: + case SDLK_O: button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_R2; axis = Input::Axis::TriggerRight; if (event->type == SDL_EVENT_KEY_DOWN) { From 4ae879875e5b1c39c0cbd54fd44212e74dc0502c Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Fri, 5 Jul 2024 15:23:35 +0300 Subject: [PATCH 02/20] scePthreadMutexTimedlock added --- .../libraries/kernel/thread_management.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index e960ec01a..3f6f9bd6a 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -840,6 +840,31 @@ int PS4_SYSV_ABI posix_pthread_mutexattr_setprotocol(ScePthreadMutexattr* attr, return result; } +int PS4_SYSV_ABI scePthreadMutexTimedlock(ScePthreadMutex* mutex, u64 usec) { + mutex = createMutex(mutex); + if (mutex == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + timespec time{}; + time.tv_sec = usec / 1000000; + time.tv_nsec = ((usec % 1000000) * 1000); + int result = pthread_mutex_timedlock(&(*mutex)->pth_mutex, &time); + + switch (result) { + case 0: + return SCE_OK; + case ETIMEDOUT: + return SCE_KERNEL_ERROR_ETIMEDOUT; + case EINTR: + return SCE_KERNEL_ERROR_EINTR; + case EAGAIN: + return SCE_KERNEL_ERROR_EAGAIN; + default: + return SCE_KERNEL_ERROR_EINVAL; + } +} + static int pthread_copy_attributes(ScePthreadAttr* dst, const ScePthreadAttr* src) { if (dst == nullptr || *dst == nullptr || src == nullptr || *src == nullptr) { return SCE_KERNEL_ERROR_EINVAL; @@ -1362,6 +1387,8 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("9UK1vLZQft4", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexLock); LIB_FUNCTION("tn3VlD0hG60", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexUnlock); LIB_FUNCTION("upoVrzMHFeE", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexTrylock); + LIB_FUNCTION("IafI2PxcPnQ", "libkernel", 1, "libkernel", 1, 1, scePthreadMutexTimedlock); + // cond calls LIB_FUNCTION("2Tb92quprl0", "libkernel", 1, "libkernel", 1, 1, scePthreadCondInit); LIB_FUNCTION("m5-2bsNfv7s", "libkernel", 1, "libkernel", 1, 1, scePthreadCondattrInit); From 56af77f1f4baa6954d68d63dcbd4745aabbc9cb7 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Fri, 5 Jul 2024 18:20:19 -0300 Subject: [PATCH 03/20] add command line arguments GUI --- src/qt_gui/main.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp index 3fc1452c3..b2ad19761 100644 --- a/src/qt_gui/main.cpp +++ b/src/qt_gui/main.cpp @@ -8,10 +8,13 @@ #include "qt_gui/game_install_dialog.h" #include "qt_gui/main_window.h" +// Custom message handler to ignore Qt logs void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {} int main(int argc, char* argv[]) { QApplication a(argc, argv); + + // Load configurations and initialize Qt application const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); Config::load(config_dir / "config.toml"); QString gameDataPath = qApp->applicationDirPath() + "/game_data/"; @@ -23,14 +26,25 @@ int main(int argc, char* argv[]) { #endif std::filesystem::create_directory(path); + // Check if the game install directory is set if (Config::getGameInstallDir() == "") { GameInstallDialog dlg; dlg.exec(); } - qInstallMessageHandler(customMessageHandler); // ignore qt logs. + // Ignore Qt logs + qInstallMessageHandler(customMessageHandler); + + // Initialize the main window MainWindow* m_main_window = new MainWindow(nullptr); m_main_window->Init(); + // Check for command line arguments + if (argc > 1) { + Core::Emulator emulator; + emulator.Run(argv[1]); + } + + // Run the Qt application return a.exec(); -} \ No newline at end of file +} From c3bf56f3ebdc9ff1e6a1fcaa21a235bb8afebc1f Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Fri, 5 Jul 2024 20:57:54 -0300 Subject: [PATCH 04/20] add 'Create Shortcut' option Added 'Create Shortcut' option to gui_context_menus Implemented functionality to create shortcuts: convertPngToIco: Converts PNG icons to ICO format. createShortcutWin: Creates shortcuts on Windows using COM interfaces. createShortcutLinux: Generates .desktop files for shortcut creation on Linux. Note: Linux functionality has not been tested. --- src/qt_gui/gui_context_menus.h | 167 +++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index c73495001..2818c3dc0 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -3,15 +3,31 @@ #pragma once +#include #include +#include #include +#include #include +#include +#include +#include #include +#include #include #include + #include "game_info.h" #include "trophy_viewer.h" +#ifdef Q_OS_WIN +#include +#include +#include +#include +#include +#endif + class GuiContextMenus : public QObject { Q_OBJECT public: @@ -27,13 +43,16 @@ public: // Setup menu. QMenu menu(widget); + QAction createShortcut("Create Shortcut", widget); QAction openFolder("Open Game Folder", widget); QAction openSfoViewer("SFO Viewer", widget); QAction openTrophyViewer("Trophy Viewer", widget); + menu.addAction(&createShortcut); menu.addAction(&openFolder); menu.addAction(&openSfoViewer); menu.addAction(&openTrophyViewer); + // Show menu. auto selected = menu.exec(global_pos); if (!selected) { @@ -105,6 +124,69 @@ public: connect(widget->parent(), &QWidget::destroyed, trophyViewer, [widget, trophyViewer]() { trophyViewer->deleteLater(); }); } + + if (selected == &createShortcut) { + QString targetPath = QString::fromStdString(m_games[itemID].path); + QString ebootPath = targetPath + "/eboot.bin"; + + // Get the full path to the icon + QString iconPath = QString::fromStdString(m_games[itemID].icon_path); + QFileInfo iconFileInfo(iconPath); + QString icoPath = iconFileInfo.absolutePath() + "/" + iconFileInfo.baseName() + ".ico"; + + // Path to shortcut/link + QString linkPath; + + // Path to the shadps4.exe executable + QString exePath; +#ifdef Q_OS_WIN + linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" + + QString::fromStdString(m_games[itemID].name) + ".lnk"; + + exePath = QCoreApplication::applicationFilePath().replace("\\", "/"); + +#else + linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" + + QString::fromStdString(m_games[itemID].name) + ".desktop"; +#endif + + // Convert the icon to .ico if necessary + if (iconFileInfo.suffix().toLower() == "png") { + // Convert icon from PNG to ICO + if (convertPngToIco(iconPath, icoPath)) { + +#ifdef Q_OS_WIN + if (createShortcutWin(linkPath, ebootPath, icoPath, exePath)) { +#else + if (createShortcutLinux(linkPath, ebootPath, iconPath)) { +#endif + QMessageBox::information( + nullptr, "Shortcut Creation", + QString("Shortcut created successfully:\n %1").arg(linkPath)); + } else { + QMessageBox::critical( + nullptr, "Error", + QString("Error creating shortcut:\n %1").arg(linkPath)); + } + } else { + QMessageBox::critical(nullptr, "Error", "Failed to convert icon."); + } + } else { + // If the icon is already in ICO format, we just create the shortcut +#ifdef Q_OS_WIN + if (createShortcutWin(linkPath, ebootPath, iconPath, exePath)) { +#else + if (createShortcutLinux(linkPath, ebootPath, iconPath)) { +#endif + QMessageBox::information( + nullptr, "Shortcut Creation", + QString("Shortcut created successfully:\n %1").arg(linkPath)); + } else { + QMessageBox::critical(nullptr, "Error", + QString("Error creating shortcut:\n %1").arg(linkPath)); + } + } + } } int GetRowIndex(QTreeWidget* treeWidget, QTreeWidgetItem* item) { @@ -155,4 +237,89 @@ public: InstallDragDropPkg(path, 1, 1); } } + +private: + bool convertPngToIco(const QString& pngFilePath, const QString& icoFilePath) { + // Load the PNG image + QImage image(pngFilePath); + if (image.isNull()) { + return false; + } + + // Scale the image to the default icon size (256x256 pixels) + QImage scaledImage = + image.scaled(QSize(256, 256), Qt::KeepAspectRatio, Qt::SmoothTransformation); + + // Convert the image to QPixmap + QPixmap pixmap = QPixmap::fromImage(scaledImage); + + // Save the pixmap as an ICO file + if (pixmap.save(icoFilePath, "ICO")) { + return true; + } else { + return false; + } + } + +#ifdef Q_OS_WIN + bool createShortcutWin(const QString& linkPath, const QString& targetPath, + const QString& iconPath, const QString& exePath) { + CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + // Create the ShellLink object + IShellLink* pShellLink = nullptr; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, + IID_IShellLink, (LPVOID*)&pShellLink); + if (SUCCEEDED(hres)) { + // Defines the path to the program executable + pShellLink->SetPath((LPCWSTR)exePath.utf16()); + + // Sets the home directory ("Start in") + pShellLink->SetWorkingDirectory((LPCWSTR)QFileInfo(exePath).absolutePath().utf16()); + + // Set arguments, eboot.bin file location + QString arguments = QString("\"%1\"").arg(targetPath); + pShellLink->SetArguments((LPCWSTR)arguments.utf16()); + + // Set the icon for the shortcut + pShellLink->SetIconLocation((LPCWSTR)iconPath.utf16(), 0); + + // Save the shortcut + IPersistFile* pPersistFile = nullptr; + hres = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile); + if (SUCCEEDED(hres)) { + hres = pPersistFile->Save((LPCWSTR)linkPath.utf16(), TRUE); + pPersistFile->Release(); + } + pShellLink->Release(); + } + + CoUninitialize(); + + return SUCCEEDED(hres); + } +#else + bool createShortcutLinux(const QString& linkPath, const QString& targetPath, + const QString& iconPath) { + QFile shortcutFile(linkPath); + if (!shortcutFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + QMessageBox::critical(nullptr, "Error", + QString("Error creating shortcut:\n %1").arg(linkPath)); + return false; + } + + QTextStream out(&shortcutFile); + out << "[Desktop Entry]\n"; + out << "Version=1.0\n"; + out << "Name=" << QFileInfo(targetPath).baseName() << "\n"; + out << "Exec=" << QCoreApplication::applicationFilePath().replace("\\", "/") << " \"" + << targetPath.replace("\\", "/") << "\"\n"; + out << "Icon=" << iconPath.replace("\\", "/") << "\n"; + out << "Terminal=false\n"; + out << "Type=Application\n"; + shortcutFile.close(); + + return true; + } +#endif }; From d4d7e9f5f632269be1258b5117454ac8605f351f Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 6 Jul 2024 10:27:57 +0300 Subject: [PATCH 05/20] removed hardware info seems make perfomance issues , will test something more lightweight --- .gitmodules | 3 --- CMakeLists.txt | 2 +- externals/CMakeLists.txt | 3 --- externals/hwinfo | 1 - src/emulator.cpp | 15 --------------- src/emulator.h | 1 - 6 files changed, 1 insertion(+), 24 deletions(-) delete mode 160000 externals/hwinfo diff --git a/.gitmodules b/.gitmodules index 5733f4fe7..d69657228 100644 --- a/.gitmodules +++ b/.gitmodules @@ -58,6 +58,3 @@ [submodule "externals/tracy"] path = externals/tracy url = https://github.com/shadps4-emu/tracy.git -[submodule "externals/hwinfo"] - path = externals/hwinfo - url = https://github.com/lfreist/hwinfo.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d91224d0..66dbe1198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -544,7 +544,7 @@ endif() create_target_directory_groups(shadps4) -target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient hwinfo::HWinfo) +target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient) target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3) if (NOT ENABLE_QT_GUI) diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index ceec21c0e..ca9c67475 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -140,6 +140,3 @@ option(TRACY_ON_DEMAND "" ON) option(TRACY_NO_FRAME_IMAGE "" ON) option(TRACY_FIBERS "" ON) # For AmdGpu frontend profiling add_subdirectory(tracy) - -# hwinfo -add_subdirectory(hwinfo) \ No newline at end of file diff --git a/externals/hwinfo b/externals/hwinfo deleted file mode 160000 index 81ea6332f..000000000 --- a/externals/hwinfo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 81ea6332fd4839890b1904f9668865145450f8da diff --git a/src/emulator.cpp b/src/emulator.cpp index 303accf31..16f202976 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -22,7 +22,6 @@ #include "core/linker.h" #include "core/memory.h" #include "emulator.h" -#include "hwinfo/hwinfo.h" Frontend::WindowSDL* g_window = nullptr; @@ -43,7 +42,6 @@ Emulator::Emulator() Common::Log::Initialize(); Common::Log::Start(); LOG_INFO(Loader, "Starting shadps4 emulator v{} ", Common::VERSION); - PrintSystemInfo(); } Emulator::~Emulator() { @@ -181,17 +179,4 @@ void Emulator::LoadSystemModules(const std::filesystem::path& file) { } } -void Emulator::PrintSystemInfo() { - auto cpus = hwinfo::getAllCPUs(); - for (const auto& cpu : cpus) { - LOG_INFO(Loader, "CPU #{} {}", cpu.id(), cpu.modelName()); - } - hwinfo::OS os; - LOG_INFO(Loader, "{}", os.name()); - auto gpus = hwinfo::getAllGPUs(); - for (auto& gpu : gpus) { - LOG_INFO(Loader, "GPU #{} {}", gpu.id(), gpu.name()); - } -} - } // namespace Core diff --git a/src/emulator.h b/src/emulator.h index fce612dc2..b61ce95e1 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -29,7 +29,6 @@ public: private: void LoadSystemModules(const std::filesystem::path& file); - void PrintSystemInfo(); Core::MemoryManager* memory; Input::GameController* controller = Common::Singleton::Instance(); From eff8a9e51491f72d034342d4519ae414881c6c13 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 6 Jul 2024 12:55:24 -0300 Subject: [PATCH 06/20] fix linux? --- src/qt_gui/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp index b2ad19761..071e12b7f 100644 --- a/src/qt_gui/main.cpp +++ b/src/qt_gui/main.cpp @@ -8,6 +8,9 @@ #include "qt_gui/game_install_dialog.h" #include "qt_gui/main_window.h" +#include +#include + // Custom message handler to ignore Qt logs void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {} From 986ed0662c024f0772b2aeb8725c751276d5d2b1 Mon Sep 17 00:00:00 2001 From: psucien Date: Fri, 5 Jul 2024 21:21:30 +0200 Subject: [PATCH 07/20] gnmdriver, amdgpu: added gpu idle IRQ; submission lock logic improved --- src/core/libraries/gnmdriver/gnmdriver.cpp | 35 +++++++++++++--------- src/core/platform.h | 1 + src/video_core/amdgpu/liverpool.cpp | 13 +------- src/video_core/amdgpu/liverpool.h | 9 ------ 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index b2c5b752e..cf1778d1e 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -3,6 +3,7 @@ #include "common/assert.h" #include "common/config.h" +#include "common/debug.h" #include "common/logging/log.h" #include "common/path_util.h" #include "common/slot_vector.h" @@ -264,6 +265,7 @@ static_assert(CtxInitSequence400.size() == 0x61); // In case if `submitDone` is issued we need to block submissions until GPU idle static u32 submission_lock{}; +std::condition_variable cv_lock{}; static std::mutex m_submission{}; static u64 frames_submitted{}; // frame counter static bool send_init_packet{true}; // initialize HW state before first game's submit in a frame @@ -277,6 +279,18 @@ struct AscQueueInfo { static Common::SlotVector asc_queues{}; static constexpr VAddr tessellation_factors_ring_addr = 0xFF0000000ULL; +static void ResetSubmissionLock(Platform::InterruptId irq) { + std::unique_lock lock{m_submission}; + submission_lock = 0; + cv_lock.notify_all(); +} + +static void WaitGpuIdle() { + HLE_TRACE; + std::unique_lock lock{m_submission}; + cv_lock.wait(lock, [] { return submission_lock == 0; }); +} + static void DumpCommandList(std::span cmd_list, const std::string& postfix) { using namespace Common::FS; const auto dump_dir = GetUserPath(PathType::PM4Dir); @@ -465,14 +479,9 @@ void PS4_SYSV_ABI sceGnmDingDong(u32 gnm_vqid, u32 next_offs_dw) { return; } - std::unique_lock lock{m_submission}; - if (submission_lock != 0) { - liverpool->WaitGpuIdle(); + WaitGpuIdle(); - // Suspend logic goes here - - submission_lock = 0; - } + /* Suspend logic goes here */ auto vqid = gnm_vqid - 1; auto& asc_queue = asc_queues[{vqid}]; @@ -1930,13 +1939,9 @@ s32 PS4_SYSV_ABI sceGnmSubmitCommandBuffers(u32 count, const u32* dcb_gpu_addrs[ } } - if (submission_lock != 0) { - liverpool->WaitGpuIdle(); + WaitGpuIdle(); - // Suspend logic goes here - - submission_lock = 0; - } + /* Suspend logic goes here */ if (send_init_packet) { if (sdk_version <= 0x1ffffffu) { @@ -1990,7 +1995,6 @@ int PS4_SYSV_ABI sceGnmSubmitDone() { if (!liverpool->IsGpuIdle()) { submission_lock = true; } - liverpool->NotifySubmitDone(); send_init_packet = true; ++frames_submitted; return ORBIS_OK; @@ -2471,6 +2475,9 @@ void RegisterlibSceGnmDriver(Core::Loader::SymbolsResolver* sym) { sdk_version = 0; } + Platform::IrqC::Instance()->Register(Platform::InterruptId::GpuIdle, ResetSubmissionLock, + nullptr); + LIB_FUNCTION("b0xyllnVY-I", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAddEqEvent); LIB_FUNCTION("b08AgtPlHPg", "libSceGnmDriver", 1, "libSceGnmDriver", 1, 1, sceGnmAreSubmitsAllowed); diff --git a/src/core/platform.h b/src/core/platform.h index d8064c52a..2c38dfd39 100644 --- a/src/core/platform.h +++ b/src/core/platform.h @@ -26,6 +26,7 @@ enum class InterruptId : u32 { Compute6RelMem = 6u, GfxEop = 7u, GfxFlip = 8u, + GpuIdle = 9u, }; using IrqHandler = std::function; diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 2c3590fe6..4bc73c671 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -66,21 +66,10 @@ void Liverpool::Process(std::stop_token stoken) { } } - if (submit_done) { - std::scoped_lock lk{submit_mutex}; - submit_cv.notify_all(); - submit_done = false; - } + Platform::IrqC::Instance()->Signal(Platform::InterruptId::GpuIdle); } } -void Liverpool::WaitGpuIdle() { - RENDERER_TRACE; - - std::unique_lock lk{submit_mutex}; - submit_cv.wait(lk, [this] { return num_submits == 0; }); -} - Liverpool::Task Liverpool::ProcessCeUpdate(std::span ccb) { TracyFiberEnter(ccb_task_name); diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index d18482f6e..e12c626d9 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -937,18 +937,10 @@ public: void SubmitGfx(std::span dcb, std::span ccb); void SubmitAsc(u32 vqid, std::span acb); - void WaitGpuIdle(); - bool IsGpuIdle() const { return num_submits == 0; } - void NotifySubmitDone() { - std::scoped_lock lk{submit_mutex}; - submit_done = true; - submit_cv.notify_all(); - } - void BindRasterizer(Vulkan::Rasterizer* rasterizer_) { rasterizer = rasterizer_; } @@ -1017,7 +1009,6 @@ private: u32 num_submits{}; std::mutex submit_mutex; std::condition_variable_any submit_cv; - std::atomic submit_done{}; }; static_assert(GFX6_3D_REG_INDEX(ps_program) == 0x2C08); From cfbe8b9e6d413cea9138386428866fd282d9a041 Mon Sep 17 00:00:00 2001 From: psucien Date: Sat, 6 Jul 2024 17:01:43 +0200 Subject: [PATCH 08/20] renderer: added support for instance step rates --- .../spirv/emit_spirv_context_get_set.cpp | 34 ++++++++++---- .../backend/spirv/spirv_emit_context.cpp | 45 ++++++++++++++++--- .../backend/spirv/spirv_emit_context.h | 3 ++ .../frontend/translate/translate.cpp | 21 +++++++-- src/shader_recompiler/runtime_info.h | 4 +- src/video_core/amdgpu/liverpool.h | 7 ++- .../renderer_vulkan/vk_graphics_pipeline.cpp | 22 ++++++++- .../renderer_vulkan/vk_graphics_pipeline.h | 12 +++-- .../renderer_vulkan/vk_rasterizer.cpp | 7 +++ 9 files changed, 129 insertions(+), 26 deletions(-) diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp index 8d8a14885..157023b69 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_context_get_set.cpp @@ -135,15 +135,33 @@ Id EmitGetAttribute(EmitContext& ctx, IR::Attribute attr, u32 comp) { if (IR::IsParam(attr)) { const u32 index{u32(attr) - u32(IR::Attribute::Param0)}; const auto& param{ctx.input_params.at(index)}; - if (!ValidId(param.id)) { - // Attribute is disabled or varying component is not written - return ctx.ConstF32(comp == 3 ? 1.0f : 0.0f); - } - if (param.num_components > 1) { - const Id pointer{ctx.OpAccessChain(param.pointer_type, param.id, ctx.ConstU32(comp))}; - return ctx.OpLoad(param.component_type, pointer); + if (param.buffer_handle < 0) { + if (!ValidId(param.id)) { + // Attribute is disabled or varying component is not written + return ctx.ConstF32(comp == 3 ? 1.0f : 0.0f); + } + + if (param.num_components > 1) { + const Id pointer{ + ctx.OpAccessChain(param.pointer_type, param.id, ctx.ConstU32(comp))}; + return ctx.OpLoad(param.component_type, pointer); + } else { + return ctx.OpLoad(param.component_type, param.id); + } } else { - return ctx.OpLoad(param.component_type, param.id); + const auto rate_idx = param.id.value == 0 ? ctx.u32_zero_value : ctx.u32_one_value; + const auto step_rate = ctx.OpLoad( + ctx.U32[1], + ctx.OpAccessChain(ctx.TypePointer(spv::StorageClass::PushConstant, ctx.U32[1]), + ctx.instance_step_rates, rate_idx)); + const auto offset = ctx.OpIAdd( + ctx.U32[1], + ctx.OpIMul( + ctx.U32[1], + ctx.OpUDiv(ctx.U32[1], ctx.OpLoad(ctx.U32[1], ctx.instance_id), step_rate), + ctx.ConstU32(param.num_components)), + ctx.ConstU32(comp)); + return EmitReadConstBuffer(ctx, param.buffer_handle, offset); } } switch (attr) { diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 6d9b25470..617458dde 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -171,17 +171,47 @@ Id MakeDefaultValue(EmitContext& ctx, u32 default_value) { void EmitContext::DefineInputs(const Info& info) { switch (stage) { - case Stage::Vertex: + case Stage::Vertex: { vertex_index = DefineVariable(U32[1], spv::BuiltIn::VertexIndex, spv::StorageClass::Input); base_vertex = DefineVariable(U32[1], spv::BuiltIn::BaseVertex, spv::StorageClass::Input); + instance_id = DefineVariable(U32[1], spv::BuiltIn::InstanceIndex, spv::StorageClass::Input); + + // Create push constants block for instance steps rates + const Id struct_type{Name(TypeStruct(U32[1], U32[1]), "instance_step_rates")}; + Decorate(struct_type, spv::Decoration::Block); + MemberName(struct_type, 0, "sr0"); + MemberName(struct_type, 1, "sr1"); + MemberDecorate(struct_type, 0, spv::Decoration::Offset, 0U); + MemberDecorate(struct_type, 1, spv::Decoration::Offset, 4U); + instance_step_rates = DefineVar(struct_type, spv::StorageClass::PushConstant); + Name(instance_step_rates, "step_rates"); + interfaces.push_back(instance_step_rates); + for (const auto& input : info.vs_inputs) { const Id type{GetAttributeType(*this, input.fmt)}; - const Id id{DefineInput(type, input.binding)}; - Name(id, fmt::format("vs_in_attr{}", input.binding)); - input_params[input.binding] = GetAttributeInfo(input.fmt, id); - interfaces.push_back(id); + if (input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate0 || + input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate1) { + + const u32 rate_idx = + input.instance_step_rate == Info::VsInput::InstanceIdType::OverStepRate0 ? 0 + : 1; + // Note that we pass index rather than Id + input_params[input.binding] = { + rate_idx, input_u32, U32[1], input.num_components, input.instance_data_buf, + }; + } else { + Id id{DefineInput(type, input.binding)}; + if (input.instance_step_rate == Info::VsInput::InstanceIdType::Plain) { + Name(id, fmt::format("vs_instance_attr{}", input.binding)); + } else { + Name(id, fmt::format("vs_in_attr{}", input.binding)); + } + input_params[input.binding] = GetAttributeInfo(input.fmt, id); + interfaces.push_back(id); + } } break; + } case Stage::Fragment: if (info.uses_group_quad) { subgroup_local_invocation_id = DefineVariable( @@ -276,7 +306,10 @@ void EmitContext::DefineBuffers(const Info& info) { if (std::ranges::find(type_ids, record_array_type.value, &Id::value) == type_ids.end()) { Decorate(record_array_type, spv::Decoration::ArrayStride, 4); const auto name = - fmt::format("{}_cbuf_block_{}{}", stage, 'f', sizeof(float) * CHAR_BIT); + buffer.is_instance_data + ? fmt::format("{}_instance_data{}_{}{}", stage, i, 'f', + sizeof(float) * CHAR_BIT) + : fmt::format("{}_cbuf_block_{}{}", stage, 'f', sizeof(float) * CHAR_BIT); Name(struct_type, name); Decorate(struct_type, spv::Decoration::Block); MemberName(struct_type, 0, "data"); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.h b/src/shader_recompiler/backend/spirv/spirv_emit_context.h index d143be4ba..b51edd639 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.h +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.h @@ -165,6 +165,8 @@ public: Id output_position{}; Id vertex_index{}; + Id instance_id{}; + Id instance_step_rates{}; Id base_vertex{}; Id frag_coord{}; Id front_facing{}; @@ -214,6 +216,7 @@ public: Id pointer_type; Id component_type; u32 num_components; + s32 buffer_handle{-1}; }; std::array input_params{}; std::array output_params{}; diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index cb6d16c34..ec5790ac8 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -235,9 +235,21 @@ void Translator::EmitFetch(const GcnInst& inst) { ir.SetVectorReg(dst_reg++, comp); } - if (attrib.instance_data == 2 || attrib.instance_data == 3) { - LOG_WARNING(Render_Recompiler, "Unsupported instance step rate = {}", - attrib.instance_data); + // In case of programmable step rates we need to fallback to instance data pulling in + // shader, so VBs should be bound as regular data buffers + s32 instance_buf_handle = -1; + const auto step_rate = static_cast(attrib.instance_data); + if (step_rate == Info::VsInput::OverStepRate0 || + step_rate == Info::VsInput::OverStepRate1) { + info.buffers.push_back({ + .sgpr_base = attrib.sgpr_base, + .dword_offset = attrib.dword_offset, + .stride = buffer.GetStride(), + .num_records = buffer.num_records, + .used_types = IR::Type::F32, + .is_instance_data = true, + }); + instance_buf_handle = s32(info.buffers.size() - 1); } const u32 num_components = AmdGpu::NumComponents(buffer.GetDataFmt()); @@ -247,7 +259,8 @@ void Translator::EmitFetch(const GcnInst& inst) { .num_components = std::min(attrib.num_elements, num_components), .sgpr_base = attrib.sgpr_base, .dword_offset = attrib.dword_offset, - .instance_step_rate = static_cast(attrib.instance_data), + .instance_step_rate = step_rate, + .instance_data_buf = instance_buf_handle, }); } } diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 66d32d4d7..6cf5c632a 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -77,7 +77,8 @@ struct BufferResource { u32 num_records; IR::Type used_types; AmdGpu::Buffer inline_cbuf; - bool is_storage; + bool is_storage{false}; + bool is_instance_data{false}; constexpr AmdGpu::Buffer GetVsharp(const Info& info) const noexcept; }; @@ -116,6 +117,7 @@ struct Info { u8 sgpr_base; u8 dword_offset; InstanceIdType instance_step_rate; + s32 instance_data_buf; }; boost::container::static_vector vs_inputs{}; diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index e12c626d9..536167ff1 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -887,7 +887,10 @@ struct Liverpool { IndexBufferType index_buffer_type; INSERT_PADDING_WORDS(0xA2A1 - 0xA29E - 2); u32 enable_primitive_id; - INSERT_PADDING_WORDS(0xA2DF - 0xA2A1 - 1); + INSERT_PADDING_WORDS(0xA2A8 - 0xA2A1 - 1); + u32 vgt_instance_step_rate_0; + u32 vgt_instance_step_rate_1; + INSERT_PADDING_WORDS(0xA2DF - 0xA2A9 - 1); PolygonOffset poly_offset; INSERT_PADDING_WORDS(0xA2F8 - 0xA2DF - 5); AaConfig aa_config; @@ -1046,6 +1049,8 @@ static_assert(GFX6_3D_REG_INDEX(vs_output_control) == 0xA207); static_assert(GFX6_3D_REG_INDEX(index_size) == 0xA29D); static_assert(GFX6_3D_REG_INDEX(index_buffer_type) == 0xA29F); static_assert(GFX6_3D_REG_INDEX(enable_primitive_id) == 0xA2A1); +static_assert(GFX6_3D_REG_INDEX(vgt_instance_step_rate_0) == 0xA2A8); +static_assert(GFX6_3D_REG_INDEX(vgt_instance_step_rate_1) == 0xA2A9); static_assert(GFX6_3D_REG_INDEX(poly_offset) == 0xA2DF); static_assert(GFX6_3D_REG_INDEX(aa_config) == 0xA2F8); static_assert(GFX6_3D_REG_INDEX(color_buffers[0].base_address) == 0xA318); diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 7b7eda442..019018369 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -30,12 +30,19 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul stages[i] = *infos[i]; } BuildDescSetLayout(); + + const vk::PushConstantRange push_constants = { + .stageFlags = vk::ShaderStageFlagBits::eVertex, + .offset = 0, + .size = 2 * sizeof(u32), + }; + const vk::DescriptorSetLayout set_layout = *desc_layout; const vk::PipelineLayoutCreateInfo layout_info = { .setLayoutCount = 1U, .pSetLayouts = &set_layout, - .pushConstantRangeCount = 0, - .pPushConstantRanges = nullptr, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &push_constants, }; pipeline_layout = instance.GetDevice().createPipelineLayoutUnique(layout_info); @@ -43,6 +50,12 @@ GraphicsPipeline::GraphicsPipeline(const Instance& instance_, Scheduler& schedul boost::container::static_vector attributes; const auto& vs_info = stages[0]; for (const auto& input : vs_info.vs_inputs) { + if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 || + input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) { + // Skip attribute binding as the data will be pulled by shader + continue; + } + const auto buffer = vs_info.ReadUd(input.sgpr_base, input.dword_offset); attributes.push_back({ .location = input.binding, @@ -420,6 +433,11 @@ void GraphicsPipeline::BindVertexBuffers(StreamBuffer& staging) const { // Calculate buffers memory overlaps boost::container::static_vector ranges{}; for (const auto& input : vs_info.vs_inputs) { + if (input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate0 || + input.instance_step_rate == Shader::Info::VsInput::InstanceIdType::OverStepRate1) { + continue; + } + const auto& buffer = vs_info.ReadUd(input.sgpr_base, input.dword_offset); if (buffer.GetSize() == 0) { continue; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 060a26953..ab8be78fb 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -67,20 +67,24 @@ public: void BindResources(Core::MemoryManager* memory, StreamBuffer& staging, VideoCore::TextureCache& texture_cache) const; - [[nodiscard]] vk::Pipeline Handle() const noexcept { + vk::Pipeline Handle() const noexcept { return *pipeline; } - [[nodiscard]] bool IsEmbeddedVs() const noexcept { + vk::PipelineLayout GetLayout() const { + return *pipeline_layout; + } + + bool IsEmbeddedVs() const noexcept { static constexpr size_t EmbeddedVsHash = 0x9b2da5cf47f8c29f; return key.stage_hashes[0] == EmbeddedVsHash; } - [[nodiscard]] auto GetWriteMasks() const { + auto GetWriteMasks() const { return key.write_masks; } - [[nodiscard]] bool IsDepthEnabled() const { + bool IsDepthEnabled() const { return key.depth.depth_enable.Value(); } diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 6440ebc76..f7059f17c 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -54,6 +54,13 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) { UpdateDynamicState(*pipeline); cmdbuf.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline->Handle()); + + const u32 step_rates[] = { + regs.vgt_instance_step_rate_0, + regs.vgt_instance_step_rate_1, + }; + cmdbuf.pushConstants(pipeline->GetLayout(), vk::ShaderStageFlagBits::eVertex, 0u, + sizeof(step_rates), &step_rates); if (is_indexed) { cmdbuf.drawIndexed(num_indices, regs.num_instances.NumInstances(), 0, 0, 0); } else { From f8e2b6d0cd008e56b82d40099bc40bcf99aa3b79 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 6 Jul 2024 13:40:26 -0300 Subject: [PATCH 09/20] fix linux --- src/qt_gui/gui_context_menus.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 2818c3dc0..4be5a557b 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -147,7 +147,7 @@ public: #else linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" + - QString::fromStdString(m_games[itemID].name) + ".desktop"; + QString::fromStdString(m_games[itemID].name); #endif // Convert the icon to .ico if necessary @@ -312,8 +312,7 @@ private: out << "[Desktop Entry]\n"; out << "Version=1.0\n"; out << "Name=" << QFileInfo(targetPath).baseName() << "\n"; - out << "Exec=" << QCoreApplication::applicationFilePath().replace("\\", "/") << " \"" - << targetPath.replace("\\", "/") << "\"\n"; + out << "Exec=" << QCoreApplication::applicationFilePath() << " \"" << targetPath << "\"\n"; out << "Icon=" << iconPath.replace("\\", "/") << "\n"; out << "Terminal=false\n"; out << "Type=Application\n"; From 311ddbe2f9045d2040eaf4f2a9810f254be18a97 Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 6 Jul 2024 13:42:53 -0300 Subject: [PATCH 10/20] fiz linux --- src/qt_gui/gui_context_menus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 4be5a557b..87d062099 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -313,7 +313,7 @@ private: out << "Version=1.0\n"; out << "Name=" << QFileInfo(targetPath).baseName() << "\n"; out << "Exec=" << QCoreApplication::applicationFilePath() << " \"" << targetPath << "\"\n"; - out << "Icon=" << iconPath.replace("\\", "/") << "\n"; + out << "Icon=" << iconPath << "\n"; out << "Terminal=false\n"; out << "Type=Application\n"; shortcutFile.close(); From d9c1456f28f7df27465ca58334250eb6a0ac1b5d Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 6 Jul 2024 15:00:18 -0300 Subject: [PATCH 11/20] fix linux again --- src/qt_gui/gui_context_menus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 87d062099..99cec9fd5 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -147,7 +147,7 @@ public: #else linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" + - QString::fromStdString(m_games[itemID].name); + QString::fromStdString(m_games[itemID].name) + ".desktop"; #endif // Convert the icon to .ico if necessary From 971d2f02ef4c1368be1b307cafa7c2973a58ba0d Mon Sep 17 00:00:00 2001 From: DanielSvoboda Date: Sat, 6 Jul 2024 15:10:28 -0300 Subject: [PATCH 12/20] fix name file shortcut linux --- src/qt_gui/gui_context_menus.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 99cec9fd5..761564461 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -311,7 +311,7 @@ private: QTextStream out(&shortcutFile); out << "[Desktop Entry]\n"; out << "Version=1.0\n"; - out << "Name=" << QFileInfo(targetPath).baseName() << "\n"; + out << "Name=" << QFileInfo(linkPath).baseName() << "\n"; out << "Exec=" << QCoreApplication::applicationFilePath() << " \"" << targetPath << "\"\n"; out << "Icon=" << iconPath << "\n"; out << "Terminal=false\n"; From 1d608427ed996b6491037b5de0d1a8ea57b8eb69 Mon Sep 17 00:00:00 2001 From: psucien Date: Sat, 6 Jul 2024 20:13:12 +0200 Subject: [PATCH 13/20] renderer: don't let unbound color attachment affect pass's rendering area --- src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 2 +- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 502746040..bf4bbc103 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -183,7 +183,7 @@ void PipelineCache::RefreshGraphicsKey() { int remapped_cb{}; for (auto cb = 0u; cb < Liverpool::NumColorBuffers; ++cb) { auto const& col_buf = regs.color_buffers[cb]; - if (!col_buf || skip_cb_binding) { + if (skip_cb_binding || !col_buf || !regs.color_target_mask.GetMask(cb)) { continue; } const auto base_format = diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index f7059f17c..997fcead2 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -106,6 +106,12 @@ void Rasterizer::BeginRendering() { continue; } + // If the color buffer is still bound but rendering to it is disabled by the target mask, + // we need to prevent the render area from being affected by unbound render target extents. + if (!regs.color_target_mask.GetMask(col_buf_id)) { + continue; + } + const auto& hint = liverpool->last_cb_extent[col_buf_id]; const auto& image_view = texture_cache.RenderTarget(col_buf, hint); const auto& image = texture_cache.GetImage(image_view.image_id); From 379ec554a8aa6e683a3a094a9f4ce8ec6da3f3e9 Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sun, 7 Jul 2024 01:26:17 +0300 Subject: [PATCH 14/20] memory: Set virtual query offset --- src/core/memory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 75faeae8b..5166908a1 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -243,6 +243,7 @@ int MemoryManager::VirtualQuery(VAddr addr, int flags, if (vma.type == VMAType::Direct) { const auto dmem_it = FindDmemArea(vma.phys_base); ASSERT(dmem_it != dmem_map.end()); + info->offset = vma.phys_base; info->memory_type = dmem_it->second.memory_type; } From bf4bf4ccb2ec5996d31e52ad570e6da00a9d6b04 Mon Sep 17 00:00:00 2001 From: psucien Date: Sun, 7 Jul 2024 13:00:52 +0200 Subject: [PATCH 15/20] recompiler: fix for gather4 components return --- src/shader_recompiler/frontend/translate/vector_memory.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index 21f3abcac..f0ef85b3b 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -165,13 +165,14 @@ void Translator::IMAGE_GATHER(const GcnInst& inst) { if (!flags.test(MimgModifier::Pcf)) { return ir.ImageGather(handle, body, offset, {}, info); } + ASSERT(mimg.dmask & 1); // should be always 1st (R) component return ir.ImageGatherDref(handle, body, offset, {}, dref, info); }(); + // For gather4 instructions dmask selects which component to read and must have + // only one bit set to 1 + ASSERT_MSG(std::popcount(mimg.dmask) == 1, "Unexpected bits in gather dmask"); for (u32 i = 0; i < 4; i++) { - if (((mimg.dmask >> i) & 1) == 0) { - continue; - } const IR::F32 value = IR::F32{ir.CompositeExtract(texel, i)}; ir.SetVectorReg(dest_reg++, value); } From 19c85c78cf7cdb7097222b2c4fb113188ad5a911 Mon Sep 17 00:00:00 2001 From: psucien Date: Sun, 7 Jul 2024 13:08:39 +0200 Subject: [PATCH 16/20] recompiler: switch instance data to storage buffers --- src/shader_recompiler/frontend/translate/translate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shader_recompiler/frontend/translate/translate.cpp b/src/shader_recompiler/frontend/translate/translate.cpp index ec5790ac8..f289933b7 100644 --- a/src/shader_recompiler/frontend/translate/translate.cpp +++ b/src/shader_recompiler/frontend/translate/translate.cpp @@ -247,6 +247,7 @@ void Translator::EmitFetch(const GcnInst& inst) { .stride = buffer.GetStride(), .num_records = buffer.num_records, .used_types = IR::Type::F32, + .is_storage = true, // we may not fit into UBO with large meshes .is_instance_data = true, }); instance_buf_handle = s32(info.buffers.size() - 1); From c7af8df2ad925540f597173e47c5ff637f15ab7a Mon Sep 17 00:00:00 2001 From: psucien Date: Sun, 7 Jul 2024 13:47:01 +0200 Subject: [PATCH 17/20] gnmdriver: added `sceGnmFindResourcesPublic` stub --- src/core/libraries/gnmdriver/gnmdriver.cpp | 10 +++++----- src/core/libraries/gnmdriver/gnmdriver.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index cf1778d1e..653607af5 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -872,9 +872,9 @@ int PS4_SYSV_ABI sceGnmEndWorkload() { return ORBIS_OK; } -int PS4_SYSV_ABI sceGnmFindResourcesPublic() { - LOG_ERROR(Lib_GnmDriver, "(STUBBED) called"); - return ORBIS_OK; +s32 PS4_SYSV_ABI sceGnmFindResourcesPublic() { + LOG_TRACE(Lib_GnmDriver, "called"); + return ORBIS_GNM_ERROR_FAILURE; // not available in retail FW } void PS4_SYSV_ABI sceGnmFlushGarlic() { @@ -1330,7 +1330,7 @@ s32 PS4_SYSV_ABI sceGnmSetEmbeddedPsShader(u32* cmdbuf, u32 size, u32 shader_id, if (shader_id > 1) { LOG_ERROR(Lib_GnmDriver, "Unknown shader id {}", shader_id); - return 0x8eee00ff; + return ORBIS_GNM_ERROR_FAILURE; } // clang-format off @@ -1400,7 +1400,7 @@ s32 PS4_SYSV_ABI sceGnmSetEmbeddedVsShader(u32* cmdbuf, u32 size, u32 shader_id, if (shader_id != 0) { LOG_ERROR(Lib_GnmDriver, "Unknown shader id {}", shader_id); - return 0x8eee00ff; + return ORBIS_GNM_ERROR_FAILURE; } // A fullscreen triangle with one uv set diff --git a/src/core/libraries/gnmdriver/gnmdriver.h b/src/core/libraries/gnmdriver/gnmdriver.h index 08099bccf..808cdf51a 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.h +++ b/src/core/libraries/gnmdriver/gnmdriver.h @@ -75,7 +75,7 @@ int PS4_SYSV_ABI sceGnmDriverInternalVirtualQuery(); int PS4_SYSV_ABI sceGnmDriverTraceInProgress(); int PS4_SYSV_ABI sceGnmDriverTriggerCapture(); int PS4_SYSV_ABI sceGnmEndWorkload(); -int PS4_SYSV_ABI sceGnmFindResourcesPublic(); +s32 PS4_SYSV_ABI sceGnmFindResourcesPublic(); void PS4_SYSV_ABI sceGnmFlushGarlic(); int PS4_SYSV_ABI sceGnmGetCoredumpAddress(); int PS4_SYSV_ABI sceGnmGetCoredumpMode(); From 6dbb842bec3a63c68a22abb516818d7539961d2f Mon Sep 17 00:00:00 2001 From: psucien Date: Sun, 7 Jul 2024 14:20:12 +0200 Subject: [PATCH 18/20] renderer: a bit more formats to support --- .../backend/spirv/spirv_emit_context.cpp | 8 ++++++++ src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 10 ++++++++++ src/video_core/texture_cache/tile_manager.cpp | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 617458dde..61ed29d5a 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -350,6 +350,14 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) { image.GetNumberFmt() == AmdGpu::NumberFormat::Float) { return spv::ImageFormat::Rg32f; } + if (image.GetDataFmt() == AmdGpu::DataFormat::Format32_32 && + image.GetNumberFmt() == AmdGpu::NumberFormat::Uint) { + return spv::ImageFormat::Rg32ui; + } + if (image.GetDataFmt() == AmdGpu::DataFormat::Format32_32_32_32 && + image.GetNumberFmt() == AmdGpu::NumberFormat::Uint) { + return spv::ImageFormat::Rgba32ui; + } if (image.GetDataFmt() == AmdGpu::DataFormat::Format16 && image.GetNumberFmt() == AmdGpu::NumberFormat::Float) { return spv::ImageFormat::R16f; diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index dca7ff3d2..64a3b7f0c 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -321,6 +321,9 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu if (data_format == AmdGpu::DataFormat::FormatBc4 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eBc4UnormBlock; } + if (data_format == AmdGpu::DataFormat::FormatBc5 && num_format == AmdGpu::NumberFormat::Unorm) { + return vk::Format::eBc5UnormBlock; + } if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && num_format == AmdGpu::NumberFormat::Sint) { return vk::Format::eR16G16B16A16Sint; @@ -366,6 +369,9 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eR8G8Unorm; } + if (data_format == AmdGpu::DataFormat::Format8_8 && num_format == AmdGpu::NumberFormat::Snorm) { + return vk::Format::eR8G8Snorm; + } if (data_format == AmdGpu::DataFormat::FormatBc7 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eBc7UnormBlock; } @@ -429,6 +435,10 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu if (data_format == AmdGpu::DataFormat::Format16 && num_format == AmdGpu::NumberFormat::Unorm) { return vk::Format::eR16Unorm; } + if (data_format == AmdGpu::DataFormat::Format16_16_16_16 && + num_format == AmdGpu::NumberFormat::Unorm) { + return vk::Format::eR16G16B16A16Unorm; + } UNREACHABLE_MSG("Unknown data_format={} and num_format={}", u32(data_format), u32(num_format)); } diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index 51af4ad80..c780ca601 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -189,10 +189,14 @@ vk::Format DemoteImageFormatForDetiling(vk::Format format) { case vk::Format::eR32Uint: return vk::Format::eR32Uint; case vk::Format::eBc1RgbaUnormBlock: + case vk::Format::eBc4UnormBlock: case vk::Format::eR32G32Sfloat: return vk::Format::eR32G32Uint; + case vk::Format::eBc2SrgbBlock: + case vk::Format::eBc2UnormBlock: case vk::Format::eBc3SrgbBlock: case vk::Format::eBc3UnormBlock: + case vk::Format::eBc5UnormBlock: case vk::Format::eBc7SrgbBlock: case vk::Format::eBc7UnormBlock: return vk::Format::eR32G32B32A32Uint; From a9f482cdfcfa13dd36feb33e8d6eb9f3dcb82678 Mon Sep 17 00:00:00 2001 From: TheTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sun, 7 Jul 2024 22:30:52 +0300 Subject: [PATCH 19/20] config: Disable splash by default --- src/common/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index f23b9d652..a577b143a 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -18,7 +18,7 @@ static std::string logFilter; static std::string logType = "sync"; static bool isDebugDump = false; static bool isLibc = true; -static bool isShowSplash = true; +static bool isShowSplash = false; static bool isNullGpu = false; static bool shouldDumpShaders = false; static bool shouldDumpPM4 = false; From 0619af24a7059cb8140a9c003bc0059f513beee3 Mon Sep 17 00:00:00 2001 From: offtkp Date: Mon, 8 Jul 2024 01:17:42 +0300 Subject: [PATCH 20/20] Eliminate compiler warning --- src/video_core/renderer_vulkan/liverpool_to_vk.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 64a3b7f0c..4280e6e69 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -222,6 +222,8 @@ vk::CompareOp DepthCompare(AmdGpu::DepthCompare comp) { return vk::CompareOp::eGreaterOrEqual; case AmdGpu::DepthCompare::Always: return vk::CompareOp::eAlways; + default: + UNREACHABLE(); } }