From c9635ec98a795265ca5399f14d85b38156146b3d Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Mon, 26 Jun 2023 22:11:43 +0200 Subject: [PATCH] early-access version 3709 --- README.md | 2 +- externals/CMakeLists.txt | 2 +- externals/vma/vma.cpp | 1 + .../yuzu/yuzu_emu/fragments/SearchFragment.kt | 6 +- .../main/java/org/yuzu/yuzu_emu/model/Game.kt | 2 +- .../org/yuzu/yuzu_emu/ui/main/MainActivity.kt | 4 +- .../java/org/yuzu/yuzu_emu/utils/FileUtil.kt | 34 ++----- .../org/yuzu/yuzu_emu/utils/GameHelper.kt | 23 ++--- src/android/app/src/main/jni/native.cpp | 91 ++++++++++--------- src/core/hid/emulated_controller.cpp | 19 +++- src/input_common/drivers/sdl_driver.cpp | 28 ++++-- src/input_common/helpers/joycon_driver.cpp | 42 +++++++-- src/input_common/helpers/joycon_driver.h | 1 + .../joycon_protocol/common_protocol.cpp | 8 +- .../backend/glasm/emit_glasm.cpp | 2 +- .../ir_opt/collect_shader_info_pass.cpp | 4 + src/shader_recompiler/shader_info.h | 1 + src/video_core/engines/maxwell_dma.cpp | 11 ++- src/video_core/host_shaders/CMakeLists.txt | 1 + .../host_shaders/opengl_lmem_warmup.comp | 47 ++++++++++ .../renderer_opengl/gl_compute_pipeline.cpp | 1 + .../renderer_opengl/gl_compute_pipeline.h | 5 + src/video_core/renderer_opengl/gl_device.cpp | 1 + src/video_core/renderer_opengl/gl_device.h | 5 + .../renderer_opengl/gl_graphics_pipeline.cpp | 1 + .../renderer_opengl/gl_graphics_pipeline.h | 5 + .../renderer_opengl/gl_rasterizer.cpp | 6 ++ .../renderer_opengl/gl_shader_manager.cpp | 13 +++ .../renderer_opengl/gl_shader_manager.h | 3 + .../vulkan_common/vulkan_device.cpp | 2 - .../vulkan_common/vulkan_memory_allocator.cpp | 2 - .../vulkan_common/vulkan_wrapper.cpp | 2 - src/yuzu/configuration/configure_ringcon.ui | 2 +- 33 files changed, 242 insertions(+), 135 deletions(-) create mode 100755 src/video_core/host_shaders/opengl_lmem_warmup.comp diff --git a/README.md b/README.md index 3fd55675d..8fa93be5f 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3708. +This is the source code for early-access 3709. ## Legal Notice diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index be9ad2789..d384e4728 100755 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -145,7 +145,7 @@ add_subdirectory(nx_tzdb) # VMA add_library(vma vma/vma.cpp) -target_include_directories(vma PUBLIC ./vma/vma/include) +target_include_directories(vma PUBLIC ./vma/VulkanMemoryAllocator/include) target_link_libraries(vma PRIVATE Vulkan::Headers) if (NOT TARGET LLVM::Demangle) diff --git a/externals/vma/vma.cpp b/externals/vma/vma.cpp index ff1acc320..1fe2cf52b 100755 --- a/externals/vma/vma.cpp +++ b/externals/vma/vma.cpp @@ -4,4 +4,5 @@ #define VMA_IMPLEMENTATION #define VMA_STATIC_VULKAN_FUNCTIONS 0 #define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 + #include \ No newline at end of file diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt index dd6c895fd..f54dccc69 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/SearchFragment.kt @@ -29,7 +29,6 @@ import org.yuzu.yuzu_emu.layout.AutofitGridLayoutManager import org.yuzu.yuzu_emu.model.Game import org.yuzu.yuzu_emu.model.GamesViewModel import org.yuzu.yuzu_emu.model.HomeViewModel -import org.yuzu.yuzu_emu.utils.FileUtil class SearchFragment : Fragment() { private var _binding: FragmentSearchBinding? = null @@ -128,10 +127,7 @@ class SearchFragment : Fragment() { R.id.chip_homebrew -> baseList.filter { it.isHomebrew } - R.id.chip_retail -> baseList.filter { - FileUtil.hasExtension(it.path, "xci") || - FileUtil.hasExtension(it.path, "nsp") - } + R.id.chip_retail -> baseList.filter { !it.isHomebrew } else -> baseList } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt index 6a048e39f..6527c64ab 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/Game.kt @@ -43,7 +43,7 @@ class Game( companion object { val extensions: Set = HashSet( - listOf(".xci", ".nsp", ".nca", ".nro") + listOf("xci", "nsp", "nca", "nro") ) } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt index 3086cfad3..f7d7aed1e 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt @@ -296,7 +296,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { return@registerForActivityResult } - if (!FileUtil.hasExtension(result, "keys")) { + if (FileUtil.getExtension(result) != "keys") { MessageDialogFragment.newInstance( R.string.reading_keys_failure, R.string.install_prod_keys_failure_extension_description @@ -393,7 +393,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider { return@registerForActivityResult } - if (!FileUtil.hasExtension(result, "bin")) { + if (FileUtil.getExtension(result) != "bin") { MessageDialogFragment.newInstance( R.string.reading_keys_failure, R.string.install_amiibo_keys_failure_extension_description diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt index 9f3bbe56f..142af5f26 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/FileUtil.kt @@ -7,7 +7,6 @@ import android.content.Context import android.database.Cursor import android.net.Uri import android.provider.DocumentsContract -import android.provider.OpenableColumns import androidx.documentfile.provider.DocumentFile import java.io.BufferedInputStream import java.io.File @@ -185,19 +184,18 @@ object FileUtil { /** * Get file display name from given path - * @param path content uri path + * @param uri content uri * @return String display name */ - fun getFilename(context: Context, path: String): String { - val resolver = context.contentResolver + fun getFilename(uri: Uri): String { + val resolver = YuzuApplication.appContext.contentResolver val columns = arrayOf( DocumentsContract.Document.COLUMN_DISPLAY_NAME ) var filename = "" var c: Cursor? = null try { - val mUri = Uri.parse(path) - c = resolver.query(mUri, columns, null, null, null) + c = resolver.query(uri, columns, null, null, null) c!!.moveToNext() filename = c.getString(0) } catch (e: Exception) { @@ -326,25 +324,9 @@ object FileUtil { } } - fun hasExtension(path: String, extension: String): Boolean = - path.substring(path.lastIndexOf(".") + 1).contains(extension) - - fun hasExtension(uri: Uri, extension: String): Boolean { - val fileName: String? - val cursor = YuzuApplication.appContext.contentResolver.query(uri, null, null, null, null) - val nameIndex = cursor?.getColumnIndex(OpenableColumns.DISPLAY_NAME) - cursor?.moveToFirst() - - if (nameIndex == null) { - return false - } - - fileName = cursor.getString(nameIndex) - cursor.close() - - if (fileName == null) { - return false - } - return fileName.substring(fileName.lastIndexOf(".") + 1).contains(extension) + fun getExtension(uri: Uri): String { + val fileName = getFilename(uri) + return fileName.substring(fileName.lastIndexOf(".") + 1) + .lowercase() } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt index ee9f3e570..f8e7eeca7 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/GameHelper.kt @@ -6,7 +6,6 @@ package org.yuzu.yuzu_emu.utils import android.content.SharedPreferences import android.net.Uri import androidx.preference.PreferenceManager -import java.util.* import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.yuzu.yuzu_emu.NativeLibrary @@ -33,15 +32,9 @@ object GameHelper { val children = FileUtil.listFiles(context, gamesUri) for (file in children) { if (!file.isDirectory) { - val filename = file.uri.toString() - val extensionStart = filename.lastIndexOf('.') - if (extensionStart > 0) { - val fileExtension = filename.substring(extensionStart) - - // Check that the file has an extension we care about before trying to read out of it. - if (Game.extensions.contains(fileExtension.lowercase(Locale.getDefault()))) { - games.add(getGame(filename)) - } + // Check that the file has an extension we care about before trying to read out of it. + if (Game.extensions.contains(FileUtil.getExtension(file.uri))) { + games.add(getGame(file.uri)) } } } @@ -59,21 +52,19 @@ object GameHelper { return games.toList() } - private fun getGame(filePath: String): Game { + private fun getGame(uri: Uri): Game { + val filePath = uri.toString() var name = NativeLibrary.getTitle(filePath) // If the game's title field is empty, use the filename. if (name.isEmpty()) { - name = filePath.substring(filePath.lastIndexOf("/") + 1) + name = FileUtil.getFilename(uri) } var gameId = NativeLibrary.getGameId(filePath) // If the game's ID field is empty, use the filename without extension. if (gameId.isEmpty()) { - gameId = filePath.substring( - filePath.lastIndexOf("/") + 1, - filePath.lastIndexOf(".") - ) + gameId = name.substring(0, name.lastIndexOf(".")) } val newGame = Game( diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index d576aac50..8bc6a4a04 100755 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -60,6 +60,9 @@ #include "video_core/rasterizer_interface.h" #include "video_core/renderer_base.h" +#define jconst [[maybe_unused]] const auto +#define jauto [[maybe_unused]] auto + namespace { class EmulationSession final { @@ -99,8 +102,8 @@ public: } int InstallFileToNand(std::string filename) { - const auto copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, - std::size_t block_size) { + jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest, + std::size_t block_size) { if (src == nullptr || dest == nullptr) { return false; } @@ -109,10 +112,10 @@ public: } using namespace Common::Literals; - std::vector buffer(1_MiB); + [[maybe_unused]] std::vector buffer(1_MiB); for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) { - const auto read = src->Read(buffer.data(), buffer.size(), i); + jconst read = src->Read(buffer.data(), buffer.size(), i); dest->Write(buffer.data(), read, i); } return true; @@ -129,14 +132,14 @@ public: m_system.SetContentProvider(std::make_unique()); m_system.GetFileSystemController().CreateFactories(*m_vfs); - std::shared_ptr nsp; + [[maybe_unused]] std::shared_ptr nsp; if (filename.ends_with("nsp")) { nsp = std::make_shared(m_vfs->OpenFile(filename, FileSys::Mode::Read)); if (nsp->IsExtractedType()) { return InstallError; } } else if (filename.ends_with("xci")) { - const auto xci = + jconst xci = std::make_shared(m_vfs->OpenFile(filename, FileSys::Mode::Read)); nsp = xci->GetSecurePartitionNSP(); } else { @@ -151,7 +154,7 @@ public: return InstallError; } - const auto res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry( + jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry( *nsp, true, copy_func); switch (res) { @@ -234,7 +237,7 @@ public: m_system.SetFilesystem(m_vfs); // Initialize system. - auto android_keyboard = std::make_unique(); + jauto android_keyboard = std::make_unique(); m_software_keyboard = android_keyboard.get(); m_system.SetShuttingDown(false); m_system.ApplySettings(); @@ -332,7 +335,7 @@ public: while (true) { { - std::unique_lock lock(m_mutex); + [[maybe_unused]] std::unique_lock lock(m_mutex); if (m_cv.wait_for(lock, std::chrono::milliseconds(800), [&]() { return !m_is_running; })) { // Emulation halted. @@ -364,7 +367,7 @@ public: } bool IsHandheldOnly() { - const auto npad_style_set = m_system.HIDCore().GetSupportedStyleTag(); + jconst npad_style_set = m_system.HIDCore().GetSupportedStyleTag(); if (npad_style_set.fullkey == 1) { return false; @@ -377,17 +380,17 @@ public: return !Settings::values.use_docked_mode.GetValue(); } - void SetDeviceType(int index, int type) { - auto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); + void SetDeviceType([[maybe_unused]] int index, int type) { + jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); controller->SetNpadStyleIndex(static_cast(type)); } - void OnGamepadConnectEvent(int index) { - auto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); + void OnGamepadConnectEvent([[maybe_unused]] int index) { + jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); // Ensure that player1 is configured correctly and handheld disconnected if (controller->GetNpadIdType() == Core::HID::NpadIdType::Player1) { - auto handheld = + jauto handheld = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld); if (controller->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::Handheld) { @@ -399,7 +402,8 @@ public: // Ensure that handheld is configured correctly and player 1 disconnected if (controller->GetNpadIdType() == Core::HID::NpadIdType::Handheld) { - auto player1 = m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); + jauto player1 = + m_system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1); if (controller->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::Handheld) { player1->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); @@ -413,8 +417,8 @@ public: } } - void OnGamepadDisconnectEvent(int index) { - auto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); + void OnGamepadDisconnectEvent([[maybe_unused]] int index) { + jauto controller = m_system.HIDCore().GetEmulatedControllerByIndex(index); controller->Disconnect(); } @@ -430,7 +434,7 @@ private: }; RomMetadata GetRomMetadata(const std::string& path) { - if (auto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) { + if (jauto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) { return search->second; } @@ -438,14 +442,14 @@ private: } RomMetadata CacheRomMetadata(const std::string& path) { - const auto file = Core::GetGameFileFromPath(m_vfs, path); - auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0); + jconst file = Core::GetGameFileFromPath(m_vfs, path); + jauto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0); RomMetadata entry; loader->ReadTitle(entry.title); loader->ReadIcon(entry.icon); if (loader->GetFileType() == Loader::FileType::NRO) { - auto loader_nro = dynamic_cast(loader.get()); + jauto loader_nro = dynamic_cast(loader.get()); entry.isHomebrew = loader_nro->IsHomebrew(); } else { entry.isHomebrew = false; @@ -516,7 +520,7 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) { SCOPE_EXIT({ EmulationSession::GetInstance().ShutdownEmulation(); }); - const auto result = EmulationSession::GetInstance().InitializeEmulation(filepath); + jconst result = EmulationSession::GetInstance().InitializeEmulation(filepath); if (result != Core::SystemResultStatus::Success) { return result; } @@ -528,24 +532,25 @@ static Core::SystemResultStatus RunEmulation(const std::string& filepath) { extern "C" { -void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, jclass clazz, jobject surf) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceChanged(JNIEnv* env, jobject instance, + [[maybe_unused]] jobject surf) { EmulationSession::GetInstance().SetNativeWindow(ANativeWindow_fromSurface(env, surf)); EmulationSession::GetInstance().SurfaceChanged(); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env, jclass clazz) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env, jobject instance) { ANativeWindow_release(EmulationSession::GetInstance().NativeWindow()); EmulationSession::GetInstance().SetNativeWindow(nullptr); EmulationSession::GetInstance().SurfaceChanged(); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jclass clazz, - jstring j_directory) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jobject instance, + [[maybe_unused]] jstring j_directory) { Common::FS::SetAppDirectory(GetJString(env, j_directory)); } -int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jclass clazz, - jstring j_file) { +int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, + [[maybe_unused]] jstring j_file) { return EmulationSession::GetInstance().InstallFileToNand(GetJString(env, j_file)); } @@ -570,7 +575,7 @@ void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeGpuDriver(JNIEnv* e } jboolean JNICALL Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_supportsCustomDriverLoading( - JNIEnv* env, [[maybe_unused]] jobject instance) { + JNIEnv* env, jobject instance) { #ifdef ARCHITECTURE_arm64 // If the KGSL device exists custom drivers can be loaded using adrenotools return SupportsCustomDriver(); @@ -648,8 +653,8 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadDisconnectEvent(JNIEnv* return static_cast(true); } jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_onGamePadButtonEvent(JNIEnv* env, jclass clazz, - [[maybe_unused]] jint j_device, - jint j_button, jint action) { + jint j_device, jint j_button, + jint action) { if (EmulationSession::GetInstance().IsRunning()) { // Ensure gamepad is connected EmulationSession::GetInstance().OnGamepadConnectEvent(j_device); @@ -718,8 +723,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased(JNIEnv* env, jclass c } jbyteArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getIcon(JNIEnv* env, jclass clazz, - [[maybe_unused]] jstring j_filename) { - auto icon_data = EmulationSession::GetInstance().GetRomIcon(GetJString(env, j_filename)); + jstring j_filename) { + jauto icon_data = EmulationSession::GetInstance().GetRomIcon(GetJString(env, j_filename)); jbyteArray icon = env->NewByteArray(static_cast(icon_data.size())); env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon), reinterpret_cast(icon_data.data())); @@ -727,8 +732,8 @@ jbyteArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getIcon(JNIEnv* env, jclass cla } jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getTitle(JNIEnv* env, jclass clazz, - [[maybe_unused]] jstring j_filename) { - auto title = EmulationSession::GetInstance().GetRomTitle(GetJString(env, j_filename)); + jstring j_filename) { + jauto title = EmulationSession::GetInstance().GetRomTitle(GetJString(env, j_filename)); return env->NewStringUTF(title.c_str()); } @@ -743,22 +748,21 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGameId(JNIEnv* env, jclass claz } jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getRegions(JNIEnv* env, jclass clazz, - [[maybe_unused]] jstring j_filename) { + jstring j_filename) { return env->NewStringUTF(""); } jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCompany(JNIEnv* env, jclass clazz, - [[maybe_unused]] jstring j_filename) { + jstring j_filename) { return env->NewStringUTF(""); } jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isHomebrew(JNIEnv* env, jclass clazz, - [[maybe_unused]] jstring j_filename) { + jstring j_filename) { return EmulationSession::GetInstance().GetIsHomebrew(GetJString(env, j_filename)); } -void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation - [[maybe_unused]] (JNIEnv* env, jclass clazz) { +void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeEmulation(JNIEnv* env, jclass clazz) { // Create the default config.ini. Config{}; // Initialize the emulated system. @@ -770,8 +774,7 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass cl } void Java_org_yuzu_yuzu_1emu_NativeLibrary_run__Ljava_lang_String_2Ljava_lang_String_2Z( - JNIEnv* env, jclass clazz, [[maybe_unused]] jstring j_file, - [[maybe_unused]] jstring j_savestate, [[maybe_unused]] jboolean j_delete_savestate) {} + JNIEnv* env, jclass clazz, jstring j_file, jstring j_savestate, jboolean j_delete_savestate) {} void Java_org_yuzu_yuzu_1emu_NativeLibrary_reloadSettings(JNIEnv* env, jclass clazz) { Config{}; @@ -816,7 +819,7 @@ jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jcl jdoubleArray j_stats = env->NewDoubleArray(4); if (EmulationSession::GetInstance().IsRunning()) { - const auto results = EmulationSession::GetInstance().PerfStats(); + jconst results = EmulationSession::GetInstance().PerfStats(); // Converting the structure into an array makes it easier to pass it to the frontend double stats[4] = {results.system_fps, results.average_game_fps, results.frametime, diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 827eb7a06..c2d61840f 100755 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -1250,6 +1250,11 @@ Common::Input::DriverResult EmulatedController::SetPollingMode( const auto virtual_nfc_result = nfc_output_device->SetPollingMode(polling_mode); const auto mapped_nfc_result = right_output_device->SetPollingMode(polling_mode); + // Restore previous state + if (mapped_nfc_result != Common::Input::DriverResult::Success) { + right_output_device->SetPollingMode(Common::Input::PollingMode::Active); + } + if (virtual_nfc_result == Common::Input::DriverResult::Success) { return virtual_nfc_result; } @@ -1329,16 +1334,22 @@ bool EmulatedController::StartNfcPolling() { auto& nfc_output_device = output_devices[static_cast(DeviceIndex::Right)]; auto& nfc_virtual_output_device = output_devices[3]; - return nfc_output_device->StartNfcPolling() == Common::Input::NfcState::Success || - nfc_virtual_output_device->StartNfcPolling() == Common::Input::NfcState::Success; + const auto device_result = nfc_output_device->StartNfcPolling(); + const auto virtual_device_result = nfc_virtual_output_device->StartNfcPolling(); + + return device_result == Common::Input::NfcState::Success || + virtual_device_result == Common::Input::NfcState::Success; } bool EmulatedController::StopNfcPolling() { auto& nfc_output_device = output_devices[static_cast(DeviceIndex::Right)]; auto& nfc_virtual_output_device = output_devices[3]; - return nfc_output_device->StopNfcPolling() == Common::Input::NfcState::Success || - nfc_virtual_output_device->StopNfcPolling() == Common::Input::NfcState::Success; + const auto device_result = nfc_output_device->StopNfcPolling(); + const auto virtual_device_result = nfc_virtual_output_device->StopNfcPolling(); + + return device_result == Common::Input::NfcState::Success || + virtual_device_result == Common::Input::NfcState::Success; } bool EmulatedController::ReadAmiiboData(std::vector& data) { diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 95df0fb2d..9fe111444 100755 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -150,6 +150,8 @@ public: if (sdl_controller) { const auto type = SDL_GameControllerGetType(sdl_controller.get()); return (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) || + (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT) || + (type == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) || (type == SDL_CONTROLLER_TYPE_PS5); } return false; @@ -228,9 +230,8 @@ public: return false; } - Common::Input::BatteryLevel GetBatteryLevel() { - const auto level = SDL_JoystickCurrentPowerLevel(sdl_joystick.get()); - switch (level) { + Common::Input::BatteryLevel GetBatteryLevel(SDL_JoystickPowerLevel battery_level) { + switch (battery_level) { case SDL_JOYSTICK_POWER_EMPTY: return Common::Input::BatteryLevel::Empty; case SDL_JOYSTICK_POWER_LOW: @@ -378,7 +379,6 @@ void SDLDriver::InitJoystick(int joystick_index) { if (joystick_map.find(guid) == joystick_map.end()) { auto joystick = std::make_shared(guid, 0, sdl_joystick, sdl_gamecontroller); PreSetController(joystick->GetPadIdentifier()); - SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); joystick->EnableMotion(); joystick_map[guid].emplace_back(std::move(joystick)); return; @@ -398,7 +398,6 @@ void SDLDriver::InitJoystick(int joystick_index) { const int port = static_cast(joystick_guid_list.size()); auto joystick = std::make_shared(guid, port, sdl_joystick, sdl_gamecontroller); PreSetController(joystick->GetPadIdentifier()); - SetBattery(joystick->GetPadIdentifier(), joystick->GetBatteryLevel()); joystick->EnableMotion(); joystick_guid_list.emplace_back(std::move(joystick)); } @@ -438,8 +437,6 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { if (const auto joystick = GetSDLJoystickBySDLID(event.jbutton.which)) { const PadIdentifier identifier = joystick->GetPadIdentifier(); SetButton(identifier, event.jbutton.button, true); - // Battery doesn't trigger an event so just update every button press - SetBattery(identifier, joystick->GetBatteryLevel()); } break; } @@ -466,6 +463,13 @@ void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) { } break; } + case SDL_JOYBATTERYUPDATED: { + if (auto joystick = GetSDLJoystickBySDLID(event.jbattery.which)) { + const PadIdentifier identifier = joystick->GetPadIdentifier(); + SetBattery(identifier, joystick->GetBatteryLevel(event.jbattery.level)); + } + break; + } case SDL_JOYDEVICEREMOVED: LOG_DEBUG(Input, "Controller removed with Instance_ID {}", event.jdevice.which); CloseJoystick(SDL_JoystickFromInstanceID(event.jdevice.which)); @@ -505,6 +509,9 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "0"); } else { SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED, "0"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS, "0"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, "1"); } // Disable hidapi drivers for pro controllers when the custom joycon driver is enabled @@ -512,8 +519,11 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "0"); } else { SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED, "0"); } + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED, "1"); + // Disable hidapi driver for xbox. Already default on Windows, this causes conflict with native // driver on Linux. SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_XBOX, "0"); @@ -793,7 +803,9 @@ ButtonMapping SDLDriver::GetButtonMappingForDevice(const Common::ParamPackage& p // This list also excludes Screenshot since there's not really a mapping for that ButtonBindings switch_to_sdl_button; - if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO) { + if (SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO || + SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT || + SDL_GameControllerGetType(controller) == SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT) { switch_to_sdl_button = GetNintendoButtonBinding(joystick); } else { switch_to_sdl_button = GetDefaultButtonBinding(); diff --git a/src/input_common/helpers/joycon_driver.cpp b/src/input_common/helpers/joycon_driver.cpp index 2c8c66951..ec984a647 100755 --- a/src/input_common/helpers/joycon_driver.cpp +++ b/src/input_common/helpers/joycon_driver.cpp @@ -72,6 +72,7 @@ DriverResult JoyconDriver::InitializeDevice() { nfc_enabled = false; passive_enabled = false; irs_enabled = false; + input_only_device = false; gyro_sensitivity = Joycon::GyroSensitivity::DPS2000; gyro_performance = Joycon::GyroPerformance::HZ833; accelerometer_sensitivity = Joycon::AccelerometerSensitivity::G8; @@ -86,16 +87,23 @@ DriverResult JoyconDriver::InitializeDevice() { rumble_protocol = std::make_unique(hidapi_handle); // Get fixed joycon info - generic_protocol->GetVersionNumber(version); - generic_protocol->SetLowPowerMode(false); - generic_protocol->GetColor(color); - if (handle_device_type == ControllerType::Pro) { - // Some 3rd party controllers aren't pro controllers - generic_protocol->GetControllerType(device_type); - } else { - device_type = handle_device_type; + if (generic_protocol->GetVersionNumber(version) != DriverResult::Success) { + // If this command fails the device doesn't accept configuration commands + input_only_device = true; } - generic_protocol->GetSerialNumber(serial_number); + + if (!input_only_device) { + generic_protocol->SetLowPowerMode(false); + generic_protocol->GetColor(color); + if (handle_device_type == ControllerType::Pro) { + // Some 3rd party controllers aren't pro controllers + generic_protocol->GetControllerType(device_type); + } else { + device_type = handle_device_type; + } + generic_protocol->GetSerialNumber(serial_number); + } + supported_features = GetSupportedFeatures(); // Get Calibration data @@ -261,6 +269,10 @@ DriverResult JoyconDriver::SetPollingMode() { generic_protocol->EnableImu(false); } + if (input_only_device) { + return DriverResult::NotSupported; + } + if (irs_protocol->IsEnabled()) { irs_protocol->DisableIrs(); } @@ -282,6 +294,7 @@ DriverResult JoyconDriver::SetPollingMode() { } irs_protocol->DisableIrs(); LOG_ERROR(Input, "Error enabling IRS"); + return result; } if (nfc_enabled && supported_features.nfc) { @@ -291,6 +304,7 @@ DriverResult JoyconDriver::SetPollingMode() { } nfc_protocol->DisableNfc(); LOG_ERROR(Input, "Error enabling NFC"); + return result; } if (hidbus_enabled && supported_features.hidbus) { @@ -305,6 +319,7 @@ DriverResult JoyconDriver::SetPollingMode() { ring_connected = false; ring_protocol->DisableRingCon(); LOG_ERROR(Input, "Error enabling Ringcon"); + return result; } if (passive_enabled && supported_features.passive) { @@ -333,6 +348,10 @@ JoyconDriver::SupportedFeatures JoyconDriver::GetSupportedFeatures() { .vibration = true, }; + if (input_only_device) { + return features; + } + if (device_type == ControllerType::Right) { features.nfc = true; features.irs = true; @@ -517,6 +536,11 @@ DriverResult JoyconDriver::StopNfcPolling() { const auto result = nfc_protocol->StopNFCPollingMode(); disable_input_thread = false; + if (amiibo_detected) { + amiibo_detected = false; + joycon_poller->UpdateAmiibo({}); + } + return result; } diff --git a/src/input_common/helpers/joycon_driver.h b/src/input_common/helpers/joycon_driver.h index bc7025a21..45b32d2f8 100755 --- a/src/input_common/helpers/joycon_driver.h +++ b/src/input_common/helpers/joycon_driver.h @@ -120,6 +120,7 @@ private: // Hardware configuration u8 leds{}; ReportMode mode{}; + bool input_only_device{}; bool passive_enabled{}; // Low power mode, Ideal for multiple controllers at the same time bool hidbus_enabled{}; // External device support bool irs_enabled{}; // Infrared camera input diff --git a/src/input_common/helpers/joycon_protocol/common_protocol.cpp b/src/input_common/helpers/joycon_protocol/common_protocol.cpp index 51669261a..88f4cec1c 100755 --- a/src/input_common/helpers/joycon_protocol/common_protocol.cpp +++ b/src/input_common/helpers/joycon_protocol/common_protocol.cpp @@ -73,7 +73,7 @@ DriverResult JoyconCommonProtocol::SendRawData(std::span buffer) { DriverResult JoyconCommonProtocol::GetSubCommandResponse(SubCommand sc, SubCommandResponse& output) { constexpr int timeout_mili = 66; - constexpr int MaxTries = 15; + constexpr int MaxTries = 3; int tries = 0; do { @@ -113,9 +113,7 @@ DriverResult JoyconCommonProtocol::SendSubCommand(SubCommand sc, std::span buffer) { @@ -158,7 +156,7 @@ DriverResult JoyconCommonProtocol::SendVibrationReport(std::span buffe DriverResult JoyconCommonProtocol::ReadRawSPI(SpiAddress addr, std::span output) { constexpr std::size_t HeaderSize = 5; - constexpr std::size_t MaxTries = 10; + constexpr std::size_t MaxTries = 5; std::size_t tries = 0; SubCommandResponse response{}; std::array buffer{}; diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index 8a153ce18..0db244dac 100755 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp @@ -461,7 +461,7 @@ std::string EmitGLASM(const Profile& profile, const RuntimeInfo& runtime_info, I header += fmt::format("R{},", index); } if (program.local_memory_size > 0) { - header += fmt::format("lmem[{}],", program.local_memory_size); + header += fmt::format("lmem[{}],", Common::DivCeil(program.local_memory_size, 4U)); } if (program.info.uses_fswzadd) { header += "FSWZA[4],FSWZB[4],"; diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index c6486d1bd..582cf91e3 100755 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp @@ -424,6 +424,10 @@ void VisitUsages(Info& info, IR::Inst& inst) { info.used_constant_buffer_types |= IR::Type::U32 | IR::Type::U32x2; info.used_storage_buffer_types |= IR::Type::U32 | IR::Type::U32x2 | IR::Type::U32x4; break; + case IR::Opcode::LoadLocal: + case IR::Opcode::WriteLocal: + info.uses_local_memory = true; + break; default: break; } diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index d4bb44d2a..705933e3d 100755 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h @@ -172,6 +172,7 @@ struct Info { bool stores_indexed_attributes{}; bool stores_global_memory{}; + bool uses_local_memory{}; bool uses_fp16{}; bool uses_fp64{}; diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index b49047e81..a3d01b404 100755 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -130,7 +130,7 @@ void MaxwellDMA::Launch() { UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); read_buffer.resize_destructive(16); for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { - memory_manager.ReadBlockUnsafe( + memory_manager.ReadBlock( convert_linear_2_blocklinear_addr(regs.offset_in + offset), read_buffer.data(), read_buffer.size()); memory_manager.WriteBlockCached(regs.offset_out + offset, read_buffer.data(), @@ -142,8 +142,8 @@ void MaxwellDMA::Launch() { UNIMPLEMENTED_IF(regs.offset_out % 16 != 0); read_buffer.resize_destructive(16); for (u32 offset = 0; offset < regs.line_length_in; offset += 16) { - memory_manager.ReadBlockUnsafe(regs.offset_in + offset, read_buffer.data(), - read_buffer.size()); + memory_manager.ReadBlock(regs.offset_in + offset, read_buffer.data(), + read_buffer.size()); memory_manager.WriteBlockCached( convert_linear_2_blocklinear_addr(regs.offset_out + offset), read_buffer.data(), read_buffer.size()); @@ -151,8 +151,9 @@ void MaxwellDMA::Launch() { } else { if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) { read_buffer.resize_destructive(regs.line_length_in); - memory_manager.ReadBlockUnsafe(regs.offset_in, read_buffer.data(), - regs.line_length_in); + memory_manager.ReadBlock(regs.offset_in, read_buffer.data(), + regs.line_length_in, + VideoCommon::CacheType::NoBufferCache); memory_manager.WriteBlockCached(regs.offset_out, read_buffer.data(), regs.line_length_in); } diff --git a/src/video_core/host_shaders/CMakeLists.txt b/src/video_core/host_shaders/CMakeLists.txt index 5cd82de24..8a0752325 100755 --- a/src/video_core/host_shaders/CMakeLists.txt +++ b/src/video_core/host_shaders/CMakeLists.txt @@ -33,6 +33,7 @@ set(SHADER_FILES opengl_fidelityfx_fsr.frag opengl_fidelityfx_fsr_easu.frag opengl_fidelityfx_fsr_rcas.frag + opengl_lmem_warmup.comp opengl_present.frag opengl_present.vert opengl_present_scaleforce.frag diff --git a/src/video_core/host_shaders/opengl_lmem_warmup.comp b/src/video_core/host_shaders/opengl_lmem_warmup.comp new file mode 100755 index 000000000..518268477 --- /dev/null +++ b/src/video_core/host_shaders/opengl_lmem_warmup.comp @@ -0,0 +1,47 @@ +// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +// This shader is a workaround for a quirk in NVIDIA OpenGL drivers +// Shaders using local memory see a great performance benefit if a shader that was dispatched +// before it had more local memory allocated. +// This shader allocates the maximum local memory allowed on NVIDIA drivers to ensure that +// subsequent shaders see the performance boost. + +// NOTE: This shader does no actual meaningful work and returns immediately, +// it is simply a means to have the driver expect a shader using lots of local memory. + +#version 450 + +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(location = 0) uniform uint uniform_data; + +layout(binding = 0, rgba8) uniform writeonly restrict image2DArray dest_image; + +#define MAX_LMEM_SIZE 4080 // Size chosen to avoid errors in Nvidia's GLSL compiler +#define NUM_LMEM_CONSTANTS 1 +#define ARRAY_SIZE MAX_LMEM_SIZE - NUM_LMEM_CONSTANTS + +uint lmem_0[ARRAY_SIZE]; +const uvec4 constant_values[NUM_LMEM_CONSTANTS] = uvec4[](uvec4(0)); + +void main() { + const uint global_id = gl_GlobalInvocationID.x; + if (global_id <= 128) { + // Since the shader is called with a dispatch of 1x1x1 + // This should always be the case, and this shader will not actually execute + return; + } + for (uint t = 0; t < uniform_data; t++) { + const uint offset = (t * uniform_data); + lmem_0[offset] = t; + } + const uint offset = (gl_GlobalInvocationID.y * uniform_data + gl_GlobalInvocationID.x); + const uint value = lmem_0[offset]; + const uint const_value = constant_values[offset / 4][offset % 4]; + const uvec4 color = uvec4(value + const_value); + + // A "side-effect" is needed so the variables don't get optimized out, + // but this should never execute so there should be no clobbering of previously bound state. + imageStore(dest_image, ivec3(gl_GlobalInvocationID), color); +} diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp index f8584541a..96325a204 100755 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.cpp @@ -63,6 +63,7 @@ ComputePipeline::ComputePipeline(const Device& device, TextureCache& texture_cac writes_global_memory = !use_storage_buffers && std::ranges::any_of(info.storage_buffers_descriptors, [](const auto& desc) { return desc.is_written; }); + uses_local_memory = info.uses_local_memory; if (force_context_flush) { std::scoped_lock lock{built_mutex}; built_fence.Create(); diff --git a/src/video_core/renderer_opengl/gl_compute_pipeline.h b/src/video_core/renderer_opengl/gl_compute_pipeline.h index e1bfc9113..53723f454 100755 --- a/src/video_core/renderer_opengl/gl_compute_pipeline.h +++ b/src/video_core/renderer_opengl/gl_compute_pipeline.h @@ -59,6 +59,10 @@ public: return writes_global_memory; } + [[nodiscard]] bool UsesLocalMemory() const noexcept { + return uses_local_memory; + } + void SetEngine(Tegra::Engines::KeplerCompute* kepler_compute_, Tegra::MemoryManager* gpu_memory_) { kepler_compute = kepler_compute_; @@ -84,6 +88,7 @@ private: bool use_storage_buffers{}; bool writes_global_memory{}; + bool uses_local_memory{}; std::mutex built_mutex; std::condition_variable built_condvar; diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 3937c30e8..d56f10b78 100755 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -194,6 +194,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) { has_bool_ref_bug = true; } } + has_lmem_perf_bug = is_nvidia; strict_context_required = emu_window.StrictContextRequired(); // Blocks AMD and Intel OpenGL drivers on Windows from using asynchronous shader compilation. diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 84acd0783..1c0a63446 100755 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -192,6 +192,10 @@ public: return supports_conditional_barriers; } + bool HasLmemPerfBug() const { + return has_lmem_perf_bug; + } + private: static bool TestVariableAoffi(); static bool TestPreciseBug(); @@ -238,6 +242,7 @@ private: bool can_report_memory{}; bool strict_context_required{}; bool supports_conditional_barriers{}; + bool has_lmem_perf_bug{}; std::string vendor_name; }; diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp index 1581edf9b..8b506cf5b 100755 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.cpp @@ -215,6 +215,7 @@ GraphicsPipeline::GraphicsPipeline(const Device& device, TextureCache& texture_c writes_global_memory |= std::ranges::any_of( info.storage_buffers_descriptors, [](const auto& desc) { return desc.is_written; }); + uses_local_memory |= info.uses_local_memory; } ASSERT(num_textures <= MAX_TEXTURES); ASSERT(num_images <= MAX_IMAGES); diff --git a/src/video_core/renderer_opengl/gl_graphics_pipeline.h b/src/video_core/renderer_opengl/gl_graphics_pipeline.h index 3ab1bb2ba..da5341746 100755 --- a/src/video_core/renderer_opengl/gl_graphics_pipeline.h +++ b/src/video_core/renderer_opengl/gl_graphics_pipeline.h @@ -98,6 +98,10 @@ public: return writes_global_memory; } + [[nodiscard]] bool UsesLocalMemory() const noexcept { + return uses_local_memory; + } + [[nodiscard]] bool IsBuilt() noexcept; template @@ -146,6 +150,7 @@ private: bool use_storage_buffers{}; bool writes_global_memory{}; + bool uses_local_memory{}; static constexpr std::size_t XFB_ENTRY_STRIDE = 3; GLsizei num_xfb_attribs{}; diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index c29e2ff60..f07f1f095 100755 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -222,6 +222,9 @@ void RasterizerOpenGL::PrepareDraw(bool is_indexed, Func&& draw_func) { gpu.TickWork(); std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex}; + if (pipeline->UsesLocalMemory()) { + program_manager.LocalMemoryWarmup(); + } pipeline->SetEngine(maxwell3d, gpu_memory); pipeline->Configure(is_indexed); @@ -371,6 +374,9 @@ void RasterizerOpenGL::DispatchCompute() { if (!pipeline) { return; } + if (pipeline->UsesLocalMemory()) { + program_manager.LocalMemoryWarmup(); + } pipeline->SetEngine(kepler_compute, gpu_memory); pipeline->Configure(); const auto& qmd{kepler_compute->launch_description}; diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 812f1b3f5..a7440ee12 100755 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp @@ -3,7 +3,9 @@ #include +#include "video_core/host_shaders/opengl_lmem_warmup_comp.h" #include "video_core/renderer_opengl/gl_shader_manager.h" +#include "video_core/renderer_opengl/gl_shader_util.h" namespace OpenGL { @@ -17,6 +19,10 @@ ProgramManager::ProgramManager(const Device& device) { if (device.UseAssemblyShaders()) { glEnable(GL_COMPUTE_PROGRAM_NV); } + if (device.HasLmemPerfBug()) { + lmem_warmup_program = + CreateProgram(HostShaders::OPENGL_LMEM_WARMUP_COMP, GL_COMPUTE_SHADER); + } } void ProgramManager::BindComputeProgram(GLuint program) { @@ -98,6 +104,13 @@ void ProgramManager::BindAssemblyPrograms(std::span current_programs{}; GLuint current_assembly_compute_program = 0; + OGLProgram lmem_warmup_program; }; } // namespace OpenGL diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 00e12e2db..8c1aa1ab9 100755 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp @@ -22,8 +22,6 @@ #include #endif -#define VMA_STATIC_VULKAN_FUNCTIONS 0 -#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #include namespace Vulkan { diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index d9f0db4a5..26eaf1cfc 100755 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -15,8 +15,6 @@ #include "video_core/vulkan_common/vulkan_memory_allocator.h" #include "video_core/vulkan_common/vulkan_wrapper.h" -#define VMA_STATIC_VULKAN_FUNCTIONS 0 -#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #include namespace Vulkan { diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 594a49a75..4553fd69d 100755 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp @@ -12,8 +12,6 @@ #include "video_core/vulkan_common/vulkan_wrapper.h" -#define VMA_STATIC_VULKAN_FUNCTIONS 0 -#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1 #include namespace Vulkan::vk { diff --git a/src/yuzu/configuration/configure_ringcon.ui b/src/yuzu/configuration/configure_ringcon.ui index b50c4a966..94e5b6da1 100755 --- a/src/yuzu/configuration/configure_ringcon.ui +++ b/src/yuzu/configuration/configure_ringcon.ui @@ -23,7 +23,7 @@ - If you want to use this controller configure player 1 as right controller and player 2 as dual joycon before starting the game to allow this controller to be detected properly. + To use Ring-Con, configure player 1 as right Joy-Con (both physical and emulated), and player 2 as left Joy-Con (left physical and dual emulated) before starting the game. true