diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | src/common/lz4_compression.cpp | 78 | ||||
| -rw-r--r-- | src/common/lz4_compression.h | 55 | ||||
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/object.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/object.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/am/am.cpp | 84 | ||||
| -rw-r--r-- | src/core/hle/service/am/am.h | 15 | ||||
| -rw-r--r-- | src/core/loader/nso.cpp | 17 | ||||
| -rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | 46 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.cpp | 17 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_manager.h | 11 | ||||
| -rw-r--r-- | src/yuzu/debugger/profiler.cpp | 1 | ||||
| -rw-r--r-- | src/yuzu/debugger/profiler.h | 9 | ||||
| -rw-r--r-- | src/yuzu/game_list.cpp | 4 | ||||
| -rw-r--r-- | src/yuzu/game_list.h | 1 | ||||
| -rw-r--r-- | src/yuzu/main.cpp | 38 | ||||
| -rw-r--r-- | src/yuzu/main.h | 1 |
21 files changed, 281 insertions, 109 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 850ce8006..5639021d3 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -91,6 +91,8 @@ add_library(common STATIC | |||
| 91 | logging/log.h | 91 | logging/log.h |
| 92 | logging/text_formatter.cpp | 92 | logging/text_formatter.cpp |
| 93 | logging/text_formatter.h | 93 | logging/text_formatter.h |
| 94 | lz4_compression.cpp | ||
| 95 | lz4_compression.h | ||
| 94 | math_util.h | 96 | math_util.h |
| 95 | memory_hook.cpp | 97 | memory_hook.cpp |
| 96 | memory_hook.h | 98 | memory_hook.h |
| @@ -136,3 +138,4 @@ endif() | |||
| 136 | create_target_directory_groups(common) | 138 | create_target_directory_groups(common) |
| 137 | 139 | ||
| 138 | target_link_libraries(common PUBLIC Boost::boost fmt microprofile) | 140 | target_link_libraries(common PUBLIC Boost::boost fmt microprofile) |
| 141 | target_link_libraries(common PRIVATE lz4_static) | ||
diff --git a/src/common/lz4_compression.cpp b/src/common/lz4_compression.cpp new file mode 100644 index 000000000..dc9b4a916 --- /dev/null +++ b/src/common/lz4_compression.cpp | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <algorithm> | ||
| 8 | #include <lz4hc.h> | ||
| 9 | |||
| 10 | #include "common/assert.h" | ||
| 11 | #include "common/lz4_compression.h" | ||
| 12 | |||
| 13 | namespace Common::Compression { | ||
| 14 | |||
| 15 | std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size) { | ||
| 16 | ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size"); | ||
| 17 | |||
| 18 | const auto source_size_int = static_cast<int>(source_size); | ||
| 19 | const int max_compressed_size = LZ4_compressBound(source_size_int); | ||
| 20 | std::vector<u8> compressed(max_compressed_size); | ||
| 21 | |||
| 22 | const int compressed_size = LZ4_compress_default(reinterpret_cast<const char*>(source), | ||
| 23 | reinterpret_cast<char*>(compressed.data()), | ||
| 24 | source_size_int, max_compressed_size); | ||
| 25 | |||
| 26 | if (compressed_size <= 0) { | ||
| 27 | // Compression failed | ||
| 28 | return {}; | ||
| 29 | } | ||
| 30 | |||
| 31 | compressed.resize(compressed_size); | ||
| 32 | |||
| 33 | return compressed; | ||
| 34 | } | ||
| 35 | |||
| 36 | std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size, | ||
| 37 | s32 compression_level) { | ||
| 38 | ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size"); | ||
| 39 | |||
| 40 | compression_level = std::clamp(compression_level, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX); | ||
| 41 | |||
| 42 | const auto source_size_int = static_cast<int>(source_size); | ||
| 43 | const int max_compressed_size = LZ4_compressBound(source_size_int); | ||
| 44 | std::vector<u8> compressed(max_compressed_size); | ||
| 45 | |||
| 46 | const int compressed_size = LZ4_compress_HC( | ||
| 47 | reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()), | ||
| 48 | source_size_int, max_compressed_size, compression_level); | ||
| 49 | |||
| 50 | if (compressed_size <= 0) { | ||
| 51 | // Compression failed | ||
| 52 | return {}; | ||
| 53 | } | ||
| 54 | |||
| 55 | compressed.resize(compressed_size); | ||
| 56 | |||
| 57 | return compressed; | ||
| 58 | } | ||
| 59 | |||
| 60 | std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size) { | ||
| 61 | return CompressDataLZ4HC(source, source_size, LZ4HC_CLEVEL_MAX); | ||
| 62 | } | ||
| 63 | |||
| 64 | std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed, | ||
| 65 | std::size_t uncompressed_size) { | ||
| 66 | std::vector<u8> uncompressed(uncompressed_size); | ||
| 67 | const int size_check = LZ4_decompress_safe(reinterpret_cast<const char*>(compressed.data()), | ||
| 68 | reinterpret_cast<char*>(uncompressed.data()), | ||
| 69 | static_cast<int>(compressed.size()), | ||
| 70 | static_cast<int>(uncompressed.size())); | ||
| 71 | if (static_cast<int>(uncompressed_size) != size_check) { | ||
| 72 | // Decompression failed | ||
| 73 | return {}; | ||
| 74 | } | ||
| 75 | return uncompressed; | ||
| 76 | } | ||
| 77 | |||
| 78 | } // namespace Common::Compression | ||
diff --git a/src/common/lz4_compression.h b/src/common/lz4_compression.h new file mode 100644 index 000000000..fe2231a6c --- /dev/null +++ b/src/common/lz4_compression.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <vector> | ||
| 6 | |||
| 7 | #include "common/common_types.h" | ||
| 8 | |||
| 9 | namespace Common::Compression { | ||
| 10 | |||
| 11 | /** | ||
| 12 | * Compresses a source memory region with LZ4 and returns the compressed data in a vector. | ||
| 13 | * | ||
| 14 | * @param source the uncompressed source memory region. | ||
| 15 | * @param source_size the size in bytes of the uncompressed source memory region. | ||
| 16 | * | ||
| 17 | * @return the compressed data. | ||
| 18 | */ | ||
| 19 | std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size); | ||
| 20 | |||
| 21 | /** | ||
| 22 | * Utilizes the LZ4 subalgorithm LZ4HC with the specified compression level. Higher compression | ||
| 23 | * levels result in a smaller compressed size, but require more CPU time for compression. The | ||
| 24 | * compression level has almost no impact on decompression speed. Data compressed with LZ4HC can | ||
| 25 | * also be decompressed with the default LZ4 decompression. | ||
| 26 | * | ||
| 27 | * @param source the uncompressed source memory region. | ||
| 28 | * @param source_size the size in bytes of the uncompressed source memory region. | ||
| 29 | * @param compression_level the used compression level. Should be between 3 and 12. | ||
| 30 | * | ||
| 31 | * @return the compressed data. | ||
| 32 | */ | ||
| 33 | std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size, s32 compression_level); | ||
| 34 | |||
| 35 | /** | ||
| 36 | * Utilizes the LZ4 subalgorithm LZ4HC with the highest possible compression level. | ||
| 37 | * | ||
| 38 | * @param source the uncompressed source memory region. | ||
| 39 | * @param source_size the size in bytes of the uncompressed source memory region. | ||
| 40 | * | ||
| 41 | * @return the compressed data. | ||
| 42 | */ | ||
| 43 | std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size); | ||
| 44 | |||
| 45 | /** | ||
| 46 | * Decompresses a source memory region with LZ4 and returns the uncompressed data in a vector. | ||
| 47 | * | ||
| 48 | * @param compressed the compressed source memory region. | ||
| 49 | * @param uncompressed_size the size in bytes of the uncompressed data. | ||
| 50 | * | ||
| 51 | * @return the decompressed data. | ||
| 52 | */ | ||
| 53 | std::vector<u8> DecompressDataLZ4(const std::vector<u8>& compressed, std::size_t uncompressed_size); | ||
| 54 | |||
| 55 | } // namespace Common::Compression \ No newline at end of file | ||
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 9e23afe85..c59107102 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -458,7 +458,7 @@ add_library(core STATIC | |||
| 458 | create_target_directory_groups(core) | 458 | create_target_directory_groups(core) |
| 459 | 459 | ||
| 460 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) | 460 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) |
| 461 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static mbedtls opus unicorn open_source_archives) | 461 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt mbedtls opus unicorn open_source_archives) |
| 462 | if (ENABLE_WEB_SERVICE) | 462 | if (ENABLE_WEB_SERVICE) |
| 463 | target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE) | 463 | target_compile_definitions(core PRIVATE -DENABLE_WEB_SERVICE) |
| 464 | target_link_libraries(core PRIVATE web_service) | 464 | target_link_libraries(core PRIVATE web_service) |
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp index 217144efc..10431e94c 100644 --- a/src/core/hle/kernel/object.cpp +++ b/src/core/hle/kernel/object.cpp | |||
| @@ -24,7 +24,6 @@ bool Object::IsWaitable() const { | |||
| 24 | case HandleType::WritableEvent: | 24 | case HandleType::WritableEvent: |
| 25 | case HandleType::SharedMemory: | 25 | case HandleType::SharedMemory: |
| 26 | case HandleType::TransferMemory: | 26 | case HandleType::TransferMemory: |
| 27 | case HandleType::AddressArbiter: | ||
| 28 | case HandleType::ResourceLimit: | 27 | case HandleType::ResourceLimit: |
| 29 | case HandleType::ClientPort: | 28 | case HandleType::ClientPort: |
| 30 | case HandleType::ClientSession: | 29 | case HandleType::ClientSession: |
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 3f6baa094..332876c27 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h | |||
| @@ -25,7 +25,6 @@ enum class HandleType : u32 { | |||
| 25 | TransferMemory, | 25 | TransferMemory, |
| 26 | Thread, | 26 | Thread, |
| 27 | Process, | 27 | Process, |
| 28 | AddressArbiter, | ||
| 29 | ResourceLimit, | 28 | ResourceLimit, |
| 30 | ClientPort, | 29 | ClientPort, |
| 31 | ServerPort, | 30 | ServerPort, |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 7d3e0e545..a13433bcf 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -239,8 +239,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger | |||
| 239 | {0, nullptr, "Exit"}, | 239 | {0, nullptr, "Exit"}, |
| 240 | {1, &ISelfController::LockExit, "LockExit"}, | 240 | {1, &ISelfController::LockExit, "LockExit"}, |
| 241 | {2, &ISelfController::UnlockExit, "UnlockExit"}, | 241 | {2, &ISelfController::UnlockExit, "UnlockExit"}, |
| 242 | {3, nullptr, "EnterFatalSection"}, | 242 | {3, &ISelfController::EnterFatalSection, "EnterFatalSection"}, |
| 243 | {4, nullptr, "LeaveFatalSection"}, | 243 | {4, &ISelfController::LeaveFatalSection, "LeaveFatalSection"}, |
| 244 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, | 244 | {9, &ISelfController::GetLibraryAppletLaunchableEvent, "GetLibraryAppletLaunchableEvent"}, |
| 245 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, | 245 | {10, &ISelfController::SetScreenShotPermission, "SetScreenShotPermission"}, |
| 246 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, | 246 | {11, &ISelfController::SetOperationModeChangedNotification, "SetOperationModeChangedNotification"}, |
| @@ -285,41 +285,54 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger | |||
| 285 | 285 | ||
| 286 | ISelfController::~ISelfController() = default; | 286 | ISelfController::~ISelfController() = default; |
| 287 | 287 | ||
| 288 | void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { | 288 | void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { |
| 289 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 290 | // u8, these are bool flags. No output. | ||
| 291 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 289 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 292 | 290 | ||
| 293 | IPC::RequestParser rp{ctx}; | 291 | IPC::ResponseBuilder rb{ctx, 2}; |
| 292 | rb.Push(RESULT_SUCCESS); | ||
| 293 | } | ||
| 294 | 294 | ||
| 295 | struct FocusHandlingModeParams { | 295 | void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { |
| 296 | u8 unknown0; | 296 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 297 | u8 unknown1; | ||
| 298 | u8 unknown2; | ||
| 299 | }; | ||
| 300 | auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 301 | 297 | ||
| 302 | IPC::ResponseBuilder rb{ctx, 2}; | 298 | IPC::ResponseBuilder rb{ctx, 2}; |
| 303 | rb.Push(RESULT_SUCCESS); | 299 | rb.Push(RESULT_SUCCESS); |
| 304 | } | 300 | } |
| 305 | 301 | ||
| 306 | void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { | 302 | void ISelfController::EnterFatalSection(Kernel::HLERequestContext& ctx) { |
| 307 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 303 | ++num_fatal_sections_entered; |
| 304 | LOG_DEBUG(Service_AM, "called. Num fatal sections entered: {}", num_fatal_sections_entered); | ||
| 308 | 305 | ||
| 309 | IPC::ResponseBuilder rb{ctx, 2}; | 306 | IPC::ResponseBuilder rb{ctx, 2}; |
| 310 | rb.Push(RESULT_SUCCESS); | 307 | rb.Push(RESULT_SUCCESS); |
| 311 | } | 308 | } |
| 312 | 309 | ||
| 313 | void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { | 310 | void ISelfController::LeaveFatalSection(Kernel::HLERequestContext& ctx) { |
| 314 | IPC::RequestParser rp{ctx}; | 311 | LOG_DEBUG(Service_AM, "called."); |
| 315 | 312 | ||
| 316 | bool flag = rp.Pop<bool>(); | 313 | // Entry and exit of fatal sections must be balanced. |
| 317 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); | 314 | if (num_fatal_sections_entered == 0) { |
| 315 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 316 | rb.Push(ResultCode{ErrorModule::AM, 512}); | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | --num_fatal_sections_entered; | ||
| 318 | 321 | ||
| 319 | IPC::ResponseBuilder rb{ctx, 2}; | 322 | IPC::ResponseBuilder rb{ctx, 2}; |
| 320 | rb.Push(RESULT_SUCCESS); | 323 | rb.Push(RESULT_SUCCESS); |
| 321 | } | 324 | } |
| 322 | 325 | ||
| 326 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { | ||
| 327 | LOG_WARNING(Service_AM, "(STUBBED) called"); | ||
| 328 | |||
| 329 | launchable_event.writable->Signal(); | ||
| 330 | |||
| 331 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 332 | rb.Push(RESULT_SUCCESS); | ||
| 333 | rb.PushCopyObjects(launchable_event.readable); | ||
| 334 | } | ||
| 335 | |||
| 323 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { | 336 | void ISelfController::SetScreenShotPermission(Kernel::HLERequestContext& ctx) { |
| 324 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 337 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 325 | 338 | ||
| @@ -337,40 +350,51 @@ void ISelfController::SetOperationModeChangedNotification(Kernel::HLERequestCont | |||
| 337 | rb.Push(RESULT_SUCCESS); | 350 | rb.Push(RESULT_SUCCESS); |
| 338 | } | 351 | } |
| 339 | 352 | ||
| 340 | void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { | 353 | void ISelfController::SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { |
| 341 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 342 | // u8, these are bool flags. No output. | ||
| 343 | IPC::RequestParser rp{ctx}; | 354 | IPC::RequestParser rp{ctx}; |
| 344 | 355 | ||
| 345 | bool enabled = rp.Pop<bool>(); | 356 | bool flag = rp.Pop<bool>(); |
| 346 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | 357 | LOG_WARNING(Service_AM, "(STUBBED) called flag={}", flag); |
| 347 | 358 | ||
| 348 | IPC::ResponseBuilder rb{ctx, 2}; | 359 | IPC::ResponseBuilder rb{ctx, 2}; |
| 349 | rb.Push(RESULT_SUCCESS); | 360 | rb.Push(RESULT_SUCCESS); |
| 350 | } | 361 | } |
| 351 | 362 | ||
| 352 | void ISelfController::LockExit(Kernel::HLERequestContext& ctx) { | 363 | void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { |
| 364 | // Takes 3 input u8s with each field located immediately after the previous | ||
| 365 | // u8, these are bool flags. No output. | ||
| 353 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 366 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 354 | 367 | ||
| 368 | IPC::RequestParser rp{ctx}; | ||
| 369 | |||
| 370 | struct FocusHandlingModeParams { | ||
| 371 | u8 unknown0; | ||
| 372 | u8 unknown1; | ||
| 373 | u8 unknown2; | ||
| 374 | }; | ||
| 375 | auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||
| 376 | |||
| 355 | IPC::ResponseBuilder rb{ctx, 2}; | 377 | IPC::ResponseBuilder rb{ctx, 2}; |
| 356 | rb.Push(RESULT_SUCCESS); | 378 | rb.Push(RESULT_SUCCESS); |
| 357 | } | 379 | } |
| 358 | 380 | ||
| 359 | void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { | 381 | void ISelfController::SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) { |
| 360 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 382 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 361 | 383 | ||
| 362 | IPC::ResponseBuilder rb{ctx, 2}; | 384 | IPC::ResponseBuilder rb{ctx, 2}; |
| 363 | rb.Push(RESULT_SUCCESS); | 385 | rb.Push(RESULT_SUCCESS); |
| 364 | } | 386 | } |
| 365 | 387 | ||
| 366 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { | 388 | void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { |
| 367 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 389 | // Takes 3 input u8s with each field located immediately after the previous |
| 390 | // u8, these are bool flags. No output. | ||
| 391 | IPC::RequestParser rp{ctx}; | ||
| 368 | 392 | ||
| 369 | launchable_event.writable->Signal(); | 393 | bool enabled = rp.Pop<bool>(); |
| 394 | LOG_WARNING(Service_AM, "(STUBBED) called enabled={}", enabled); | ||
| 370 | 395 | ||
| 371 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 396 | IPC::ResponseBuilder rb{ctx, 2}; |
| 372 | rb.Push(RESULT_SUCCESS); | 397 | rb.Push(RESULT_SUCCESS); |
| 373 | rb.PushCopyObjects(launchable_event.readable); | ||
| 374 | } | 398 | } |
| 375 | 399 | ||
| 376 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { | 400 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 565dd8e9e..991b7d47c 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -117,17 +117,19 @@ public: | |||
| 117 | ~ISelfController() override; | 117 | ~ISelfController() override; |
| 118 | 118 | ||
| 119 | private: | 119 | private: |
| 120 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); | ||
| 121 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); | ||
| 122 | void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 123 | void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 124 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); | ||
| 125 | void LockExit(Kernel::HLERequestContext& ctx); | 120 | void LockExit(Kernel::HLERequestContext& ctx); |
| 126 | void UnlockExit(Kernel::HLERequestContext& ctx); | 121 | void UnlockExit(Kernel::HLERequestContext& ctx); |
| 122 | void EnterFatalSection(Kernel::HLERequestContext& ctx); | ||
| 123 | void LeaveFatalSection(Kernel::HLERequestContext& ctx); | ||
| 127 | void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); | 124 | void GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx); |
| 125 | void SetScreenShotPermission(Kernel::HLERequestContext& ctx); | ||
| 126 | void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 127 | void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx); | ||
| 128 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); | ||
| 129 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); | ||
| 130 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); | ||
| 128 | void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); | 131 | void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); |
| 129 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); | 132 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); |
| 130 | void SetScreenShotPermission(Kernel::HLERequestContext& ctx); | ||
| 131 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); | 133 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); |
| 132 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); | 134 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); |
| 133 | void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); | 135 | void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); |
| @@ -135,6 +137,7 @@ private: | |||
| 135 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 137 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 136 | Kernel::EventPair launchable_event; | 138 | Kernel::EventPair launchable_event; |
| 137 | u32 idle_time_detection_extension = 0; | 139 | u32 idle_time_detection_extension = 0; |
| 140 | u64 num_fatal_sections_entered = 0; | ||
| 138 | }; | 141 | }; |
| 139 | 142 | ||
| 140 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { | 143 | class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index babc7e646..ffe2eea8a 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -4,11 +4,12 @@ | |||
| 4 | 4 | ||
| 5 | #include <cinttypes> | 5 | #include <cinttypes> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | #include <lz4.h> | 7 | |
| 8 | #include "common/common_funcs.h" | 8 | #include "common/common_funcs.h" |
| 9 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 10 | #include "common/hex_util.h" | 10 | #include "common/hex_util.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/lz4_compression.h" | ||
| 12 | #include "common/swap.h" | 13 | #include "common/swap.h" |
| 13 | #include "core/core.h" | 14 | #include "core/core.h" |
| 14 | #include "core/file_sys/patch_manager.h" | 15 | #include "core/file_sys/patch_manager.h" |
| @@ -35,15 +36,11 @@ static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size."); | |||
| 35 | 36 | ||
| 36 | std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data, | 37 | std::vector<u8> DecompressSegment(const std::vector<u8>& compressed_data, |
| 37 | const NSOSegmentHeader& header) { | 38 | const NSOSegmentHeader& header) { |
| 38 | std::vector<u8> uncompressed_data(header.size); | 39 | const std::vector<u8> uncompressed_data = |
| 39 | const int bytes_uncompressed = | 40 | Common::Compression::DecompressDataLZ4(compressed_data, header.size); |
| 40 | LZ4_decompress_safe(reinterpret_cast<const char*>(compressed_data.data()), | 41 | |
| 41 | reinterpret_cast<char*>(uncompressed_data.data()), | 42 | ASSERT_MSG(uncompressed_data.size() == static_cast<int>(header.size), "{} != {}", header.size, |
| 42 | static_cast<int>(compressed_data.size()), header.size); | 43 | uncompressed_data.size()); |
| 43 | |||
| 44 | ASSERT_MSG(bytes_uncompressed == static_cast<int>(header.size) && | ||
| 45 | bytes_uncompressed == static_cast<int>(uncompressed_data.size()), | ||
| 46 | "{} != {} != {}", bytes_uncompressed, header.size, uncompressed_data.size()); | ||
| 47 | 44 | ||
| 48 | return uncompressed_data; | 45 | return uncompressed_data; |
| 49 | } | 46 | } |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 44c761d3e..242a0d1cd 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -139,4 +139,4 @@ endif() | |||
| 139 | create_target_directory_groups(video_core) | 139 | create_target_directory_groups(video_core) |
| 140 | 140 | ||
| 141 | target_link_libraries(video_core PUBLIC common core) | 141 | target_link_libraries(video_core PUBLIC common core) |
| 142 | target_link_libraries(video_core PRIVATE glad lz4_static) | 142 | target_link_libraries(video_core PRIVATE glad) |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 046fc935b..8f012db62 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -318,7 +318,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 318 | const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5 | 318 | const std::size_t stage{index == 0 ? 0 : index - 1}; // Stage indices are 0 - 5 |
| 319 | 319 | ||
| 320 | GLShader::MaxwellUniformData ubo{}; | 320 | GLShader::MaxwellUniformData ubo{}; |
| 321 | ubo.SetFromRegs(gpu.state.shader_stages[stage]); | 321 | ubo.SetFromRegs(gpu, stage); |
| 322 | const GLintptr offset = buffer_cache.UploadHostMemory( | 322 | const GLintptr offset = buffer_cache.UploadHostMemory( |
| 323 | &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); | 323 | &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); |
| 324 | 324 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 290e654bc..7030db365 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -6,13 +6,11 @@ | |||
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "common/hash.h" | 7 | #include "common/hash.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/memory.h" | ||
| 10 | #include "video_core/engines/maxwell_3d.h" | 9 | #include "video_core/engines/maxwell_3d.h" |
| 11 | #include "video_core/renderer_opengl/gl_rasterizer.h" | 10 | #include "video_core/renderer_opengl/gl_rasterizer.h" |
| 12 | #include "video_core/renderer_opengl/gl_shader_cache.h" | 11 | #include "video_core/renderer_opengl/gl_shader_cache.h" |
| 13 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" | 12 | #include "video_core/renderer_opengl/gl_shader_decompiler.h" |
| 14 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" | 13 | #include "video_core/renderer_opengl/gl_shader_disk_cache.h" |
| 15 | #include "video_core/renderer_opengl/gl_shader_manager.h" | ||
| 16 | #include "video_core/renderer_opengl/utils.h" | 14 | #include "video_core/renderer_opengl/utils.h" |
| 17 | #include "video_core/shader/shader_ir.h" | 15 | #include "video_core/shader/shader_ir.h" |
| 18 | 16 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp index 82fc4d44b..d2d979997 100644 --- a/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_disk_cache.cpp | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <fmt/format.h> | 6 | #include <fmt/format.h> |
| 7 | #include <lz4.h> | ||
| 8 | 7 | ||
| 9 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 10 | #include "common/common_paths.h" | 9 | #include "common/common_paths.h" |
| 11 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 12 | #include "common/file_util.h" | 11 | #include "common/file_util.h" |
| 13 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "common/lz4_compression.h" | ||
| 14 | #include "common/scm_rev.h" | 14 | #include "common/scm_rev.h" |
| 15 | 15 | ||
| 16 | #include "core/core.h" | 16 | #include "core/core.h" |
| @@ -49,39 +49,6 @@ ShaderCacheVersionHash GetShaderCacheVersionHash() { | |||
| 49 | return hash; | 49 | return hash; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | template <typename T> | ||
| 53 | std::vector<u8> CompressData(const T* source, std::size_t source_size) { | ||
| 54 | if (source_size > LZ4_MAX_INPUT_SIZE) { | ||
| 55 | // Source size exceeds LZ4 maximum input size | ||
| 56 | return {}; | ||
| 57 | } | ||
| 58 | const auto source_size_int = static_cast<int>(source_size); | ||
| 59 | const int max_compressed_size = LZ4_compressBound(source_size_int); | ||
| 60 | std::vector<u8> compressed(max_compressed_size); | ||
| 61 | const int compressed_size = LZ4_compress_default(reinterpret_cast<const char*>(source), | ||
| 62 | reinterpret_cast<char*>(compressed.data()), | ||
| 63 | source_size_int, max_compressed_size); | ||
| 64 | if (compressed_size <= 0) { | ||
| 65 | // Compression failed | ||
| 66 | return {}; | ||
| 67 | } | ||
| 68 | compressed.resize(compressed_size); | ||
| 69 | return compressed; | ||
| 70 | } | ||
| 71 | |||
| 72 | std::vector<u8> DecompressData(const std::vector<u8>& compressed, std::size_t uncompressed_size) { | ||
| 73 | std::vector<u8> uncompressed(uncompressed_size); | ||
| 74 | const int size_check = LZ4_decompress_safe(reinterpret_cast<const char*>(compressed.data()), | ||
| 75 | reinterpret_cast<char*>(uncompressed.data()), | ||
| 76 | static_cast<int>(compressed.size()), | ||
| 77 | static_cast<int>(uncompressed.size())); | ||
| 78 | if (static_cast<int>(uncompressed_size) != size_check) { | ||
| 79 | // Decompression failed | ||
| 80 | return {}; | ||
| 81 | } | ||
| 82 | return uncompressed; | ||
| 83 | } | ||
| 84 | |||
| 85 | } // namespace | 52 | } // namespace |
| 86 | 53 | ||
| 87 | ShaderDiskCacheRaw::ShaderDiskCacheRaw(u64 unique_identifier, Maxwell::ShaderProgram program_type, | 54 | ShaderDiskCacheRaw::ShaderDiskCacheRaw(u64 unique_identifier, Maxwell::ShaderProgram program_type, |
| @@ -292,7 +259,7 @@ ShaderDiskCacheOpenGL::LoadPrecompiledFile(FileUtil::IOFile& file) { | |||
| 292 | return {}; | 259 | return {}; |
| 293 | } | 260 | } |
| 294 | 261 | ||
| 295 | dump.binary = DecompressData(compressed_binary, binary_length); | 262 | dump.binary = Common::Compression::DecompressDataLZ4(compressed_binary, binary_length); |
| 296 | if (dump.binary.empty()) { | 263 | if (dump.binary.empty()) { |
| 297 | return {}; | 264 | return {}; |
| 298 | } | 265 | } |
| @@ -321,7 +288,7 @@ std::optional<ShaderDiskCacheDecompiled> ShaderDiskCacheOpenGL::LoadDecompiledEn | |||
| 321 | return {}; | 288 | return {}; |
| 322 | } | 289 | } |
| 323 | 290 | ||
| 324 | const std::vector<u8> code = DecompressData(compressed_code, code_size); | 291 | const std::vector<u8> code = Common::Compression::DecompressDataLZ4(compressed_code, code_size); |
| 325 | if (code.empty()) { | 292 | if (code.empty()) { |
| 326 | return {}; | 293 | return {}; |
| 327 | } | 294 | } |
| @@ -507,7 +474,8 @@ void ShaderDiskCacheOpenGL::SaveDecompiled(u64 unique_identifier, const std::str | |||
| 507 | if (!IsUsable()) | 474 | if (!IsUsable()) |
| 508 | return; | 475 | return; |
| 509 | 476 | ||
| 510 | const std::vector<u8> compressed_code{CompressData(code.data(), code.size())}; | 477 | const std::vector<u8> compressed_code{Common::Compression::CompressDataLZ4HC( |
| 478 | reinterpret_cast<const u8*>(code.data()), code.size(), 9)}; | ||
| 511 | if (compressed_code.empty()) { | 479 | if (compressed_code.empty()) { |
| 512 | LOG_ERROR(Render_OpenGL, "Failed to compress GLSL code - skipping shader {:016x}", | 480 | LOG_ERROR(Render_OpenGL, "Failed to compress GLSL code - skipping shader {:016x}", |
| 513 | unique_identifier); | 481 | unique_identifier); |
| @@ -537,7 +505,9 @@ void ShaderDiskCacheOpenGL::SaveDump(const ShaderDiskCacheUsage& usage, GLuint p | |||
| 537 | std::vector<u8> binary(binary_length); | 505 | std::vector<u8> binary(binary_length); |
| 538 | glGetProgramBinary(program, binary_length, nullptr, &binary_format, binary.data()); | 506 | glGetProgramBinary(program, binary_length, nullptr, &binary_format, binary.data()); |
| 539 | 507 | ||
| 540 | const std::vector<u8> compressed_binary = CompressData(binary.data(), binary.size()); | 508 | const std::vector<u8> compressed_binary = |
| 509 | Common::Compression::CompressDataLZ4HC(binary.data(), binary.size(), 9); | ||
| 510 | |||
| 541 | if (compressed_binary.empty()) { | 511 | if (compressed_binary.empty()) { |
| 542 | LOG_ERROR(Render_OpenGL, "Failed to compress binary program in shader={:016x}", | 512 | LOG_ERROR(Render_OpenGL, "Failed to compress binary program in shader={:016x}", |
| 543 | usage.unique_identifier); | 513 | usage.unique_identifier); |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.cpp b/src/video_core/renderer_opengl/gl_shader_manager.cpp index 6a30c28d2..eaf3e03a0 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.cpp +++ b/src/video_core/renderer_opengl/gl_shader_manager.cpp | |||
| @@ -2,15 +2,15 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "video_core/renderer_opengl/gl_shader_manager.h" | 5 | #include "video_core/renderer_opengl/gl_shader_manager.h" |
| 7 | 6 | ||
| 8 | namespace OpenGL::GLShader { | 7 | namespace OpenGL::GLShader { |
| 9 | 8 | ||
| 10 | void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage) { | 9 | using Tegra::Engines::Maxwell3D; |
| 11 | const auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); | 10 | |
| 12 | const auto& regs = gpu.regs; | 11 | void MaxwellUniformData::SetFromRegs(const Maxwell3D& maxwell, std::size_t shader_stage) { |
| 13 | const auto& state = gpu.state; | 12 | const auto& regs = maxwell.regs; |
| 13 | const auto& state = maxwell.state; | ||
| 14 | 14 | ||
| 15 | // TODO(bunnei): Support more than one viewport | 15 | // TODO(bunnei): Support more than one viewport |
| 16 | viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; | 16 | viewport_flip[0] = regs.viewport_transform[0].scale_x < 0.0 ? -1.0f : 1.0f; |
| @@ -18,7 +18,7 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& sh | |||
| 18 | 18 | ||
| 19 | u32 func = static_cast<u32>(regs.alpha_test_func); | 19 | u32 func = static_cast<u32>(regs.alpha_test_func); |
| 20 | // Normalize the gl variants of opCompare to be the same as the normal variants | 20 | // Normalize the gl variants of opCompare to be the same as the normal variants |
| 21 | u32 op_gl_variant_base = static_cast<u32>(Tegra::Engines::Maxwell3D::Regs::ComparisonOp::Never); | 21 | const u32 op_gl_variant_base = static_cast<u32>(Maxwell3D::Regs::ComparisonOp::Never); |
| 22 | if (func >= op_gl_variant_base) { | 22 | if (func >= op_gl_variant_base) { |
| 23 | func = func - op_gl_variant_base + 1U; | 23 | func = func - op_gl_variant_base + 1U; |
| 24 | } | 24 | } |
| @@ -31,8 +31,9 @@ void MaxwellUniformData::SetFromRegs(const Maxwell3D::State::ShaderStageInfo& sh | |||
| 31 | 31 | ||
| 32 | // Assign in which stage the position has to be flipped | 32 | // Assign in which stage the position has to be flipped |
| 33 | // (the last stage before the fragment shader). | 33 | // (the last stage before the fragment shader). |
| 34 | if (gpu.regs.shader_config[static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry)].enable) { | 34 | constexpr u32 geometry_index = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry); |
| 35 | flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::Geometry); | 35 | if (maxwell.regs.shader_config[geometry_index].enable) { |
| 36 | flip_stage = geometry_index; | ||
| 36 | } else { | 37 | } else { |
| 37 | flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB); | 38 | flip_stage = static_cast<u32>(Maxwell3D::Regs::ShaderProgram::VertexB); |
| 38 | } | 39 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index 4970aafed..8eef2a920 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -12,14 +12,13 @@ | |||
| 12 | 12 | ||
| 13 | namespace OpenGL::GLShader { | 13 | namespace OpenGL::GLShader { |
| 14 | 14 | ||
| 15 | using Tegra::Engines::Maxwell3D; | ||
| 16 | |||
| 17 | /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned | 15 | /// Uniform structure for the Uniform Buffer Object, all vectors must be 16-byte aligned |
| 18 | // NOTE: Always keep a vec4 at the end. The GL spec is not clear whether the alignment at | 16 | /// @note Always keep a vec4 at the end. The GL spec is not clear whether the alignment at |
| 19 | // the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. | 17 | /// the end of a uniform block is included in UNIFORM_BLOCK_DATA_SIZE or not. |
| 20 | // Not following that rule will cause problems on some AMD drivers. | 18 | /// Not following that rule will cause problems on some AMD drivers. |
| 21 | struct MaxwellUniformData { | 19 | struct MaxwellUniformData { |
| 22 | void SetFromRegs(const Maxwell3D::State::ShaderStageInfo& shader_stage); | 20 | void SetFromRegs(const Tegra::Engines::Maxwell3D& maxwell, std::size_t shader_stage); |
| 21 | |||
| 23 | alignas(16) GLvec4 viewport_flip; | 22 | alignas(16) GLvec4 viewport_flip; |
| 24 | struct alignas(16) { | 23 | struct alignas(16) { |
| 25 | GLuint instance_id; | 24 | GLuint instance_id; |
diff --git a/src/yuzu/debugger/profiler.cpp b/src/yuzu/debugger/profiler.cpp index 8b30e0a85..86e03e46d 100644 --- a/src/yuzu/debugger/profiler.cpp +++ b/src/yuzu/debugger/profiler.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <QMouseEvent> | 7 | #include <QMouseEvent> |
| 8 | #include <QPainter> | 8 | #include <QPainter> |
| 9 | #include <QString> | 9 | #include <QString> |
| 10 | #include <QTimer> | ||
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 11 | #include "common/microprofile.h" | 12 | #include "common/microprofile.h" |
| 12 | #include "yuzu/debugger/profiler.h" | 13 | #include "yuzu/debugger/profiler.h" |
diff --git a/src/yuzu/debugger/profiler.h b/src/yuzu/debugger/profiler.h index eae1e9e3c..8e69fdb06 100644 --- a/src/yuzu/debugger/profiler.h +++ b/src/yuzu/debugger/profiler.h | |||
| @@ -4,10 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <QAbstractItemModel> | 7 | #include <QWidget> |
| 8 | #include <QDockWidget> | 8 | |
| 9 | #include <QTimer> | 9 | class QAction; |
| 10 | #include "common/microprofile.h" | 10 | class QHideEvent; |
| 11 | class QShowEvent; | ||
| 11 | 12 | ||
| 12 | class MicroProfileDialog : public QWidget { | 13 | class MicroProfileDialog : public QWidget { |
| 13 | Q_OBJECT | 14 | Q_OBJECT |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index c0e3c5fa9..4422a572b 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -329,6 +329,8 @@ void GameList::PopupContextMenu(const QPoint& menu_location) { | |||
| 329 | QMenu context_menu; | 329 | QMenu context_menu; |
| 330 | QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); | 330 | QAction* open_save_location = context_menu.addAction(tr("Open Save Data Location")); |
| 331 | QAction* open_lfs_location = context_menu.addAction(tr("Open Mod Data Location")); | 331 | QAction* open_lfs_location = context_menu.addAction(tr("Open Mod Data Location")); |
| 332 | QAction* open_transferable_shader_cache = | ||
| 333 | context_menu.addAction(tr("Open Transferable Shader Cache")); | ||
| 332 | context_menu.addSeparator(); | 334 | context_menu.addSeparator(); |
| 333 | QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS")); | 335 | QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS")); |
| 334 | QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard")); | 336 | QAction* copy_tid = context_menu.addAction(tr("Copy Title ID to Clipboard")); |
| @@ -344,6 +346,8 @@ void GameList::PopupContextMenu(const QPoint& menu_location) { | |||
| 344 | [&]() { emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData); }); | 346 | [&]() { emit OpenFolderRequested(program_id, GameListOpenTarget::SaveData); }); |
| 345 | connect(open_lfs_location, &QAction::triggered, | 347 | connect(open_lfs_location, &QAction::triggered, |
| 346 | [&]() { emit OpenFolderRequested(program_id, GameListOpenTarget::ModData); }); | 348 | [&]() { emit OpenFolderRequested(program_id, GameListOpenTarget::ModData); }); |
| 349 | connect(open_transferable_shader_cache, &QAction::triggered, | ||
| 350 | [&]() { emit OpenTransferableShaderCacheRequested(program_id); }); | ||
| 347 | connect(dump_romfs, &QAction::triggered, [&]() { emit DumpRomFSRequested(program_id, path); }); | 351 | connect(dump_romfs, &QAction::triggered, [&]() { emit DumpRomFSRequested(program_id, path); }); |
| 348 | connect(copy_tid, &QAction::triggered, [&]() { emit CopyTIDRequested(program_id); }); | 352 | connect(copy_tid, &QAction::triggered, [&]() { emit CopyTIDRequested(program_id); }); |
| 349 | connect(navigate_to_gamedb_entry, &QAction::triggered, | 353 | connect(navigate_to_gamedb_entry, &QAction::triggered, |
diff --git a/src/yuzu/game_list.h b/src/yuzu/game_list.h index b317eb2fc..8ea5cbaaa 100644 --- a/src/yuzu/game_list.h +++ b/src/yuzu/game_list.h | |||
| @@ -66,6 +66,7 @@ signals: | |||
| 66 | void GameChosen(QString game_path); | 66 | void GameChosen(QString game_path); |
| 67 | void ShouldCancelWorker(); | 67 | void ShouldCancelWorker(); |
| 68 | void OpenFolderRequested(u64 program_id, GameListOpenTarget target); | 68 | void OpenFolderRequested(u64 program_id, GameListOpenTarget target); |
| 69 | void OpenTransferableShaderCacheRequested(u64 program_id); | ||
| 69 | void DumpRomFSRequested(u64 program_id, const std::string& game_path); | 70 | void DumpRomFSRequested(u64 program_id, const std::string& game_path); |
| 70 | void CopyTIDRequested(u64 program_id); | 71 | void CopyTIDRequested(u64 program_id); |
| 71 | void NavigateToGamedbEntryRequested(u64 program_id, | 72 | void NavigateToGamedbEntryRequested(u64 program_id, |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 41ba3c4c6..9efe626d0 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -648,6 +648,8 @@ void GMainWindow::RestoreUIState() { | |||
| 648 | void GMainWindow::ConnectWidgetEvents() { | 648 | void GMainWindow::ConnectWidgetEvents() { |
| 649 | connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile); | 649 | connect(game_list, &GameList::GameChosen, this, &GMainWindow::OnGameListLoadFile); |
| 650 | connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); | 650 | connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder); |
| 651 | connect(game_list, &GameList::OpenTransferableShaderCacheRequested, this, | ||
| 652 | &GMainWindow::OnTransferableShaderCacheOpenFile); | ||
| 651 | connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS); | 653 | connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS); |
| 652 | connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID); | 654 | connect(game_list, &GameList::CopyTIDRequested, this, &GMainWindow::OnGameListCopyTID); |
| 653 | connect(game_list, &GameList::NavigateToGamedbEntryRequested, this, | 655 | connect(game_list, &GameList::NavigateToGamedbEntryRequested, this, |
| @@ -1082,6 +1084,42 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target | |||
| 1082 | QDesktopServices::openUrl(QUrl::fromLocalFile(qpath)); | 1084 | QDesktopServices::openUrl(QUrl::fromLocalFile(qpath)); |
| 1083 | } | 1085 | } |
| 1084 | 1086 | ||
| 1087 | void GMainWindow::OnTransferableShaderCacheOpenFile(u64 program_id) { | ||
| 1088 | ASSERT(program_id != 0); | ||
| 1089 | |||
| 1090 | constexpr char open_target[] = "Transferable Shader Cache"; | ||
| 1091 | const QString tranferable_shader_cache_folder_path = | ||
| 1092 | QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::ShaderDir)) + "opengl" + | ||
| 1093 | DIR_SEP + "transferable"; | ||
| 1094 | |||
| 1095 | const QString transferable_shader_cache_file_path = | ||
| 1096 | tranferable_shader_cache_folder_path + DIR_SEP + | ||
| 1097 | QString::fromStdString(fmt::format("{:016X}", program_id)) + ".bin"; | ||
| 1098 | |||
| 1099 | if (!QFile(transferable_shader_cache_file_path).exists()) { | ||
| 1100 | QMessageBox::warning(this, | ||
| 1101 | tr("Error Opening %1 File").arg(QString::fromStdString(open_target)), | ||
| 1102 | tr("File does not exist!")); | ||
| 1103 | return; | ||
| 1104 | } | ||
| 1105 | LOG_INFO(Frontend, "Opening {} path for program_id={:016x}", open_target, program_id); | ||
| 1106 | |||
| 1107 | // Windows supports opening a folder with selecting a specified file in explorer. On every other | ||
| 1108 | // OS we just open the transferable shader cache folder without preselecting the transferable | ||
| 1109 | // shader cache file for the selected game. | ||
| 1110 | #if defined(Q_OS_WIN) | ||
| 1111 | const QString explorer = "explorer"; | ||
| 1112 | QStringList param; | ||
| 1113 | if (!QFileInfo(transferable_shader_cache_file_path).isDir()) { | ||
| 1114 | param << QLatin1String("/select,"); | ||
| 1115 | } | ||
| 1116 | param << QDir::toNativeSeparators(transferable_shader_cache_file_path); | ||
| 1117 | QProcess::startDetached(explorer, param); | ||
| 1118 | #else | ||
| 1119 | QDesktopServices::openUrl(QUrl::fromLocalFile(tranferable_shader_cache_folder_path)); | ||
| 1120 | #endif | ||
| 1121 | } | ||
| 1122 | |||
| 1085 | static std::size_t CalculateRomFSEntrySize(const FileSys::VirtualDir& dir, bool full) { | 1123 | static std::size_t CalculateRomFSEntrySize(const FileSys::VirtualDir& dir, bool full) { |
| 1086 | std::size_t out = 0; | 1124 | std::size_t out = 0; |
| 1087 | 1125 | ||
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index e07c892cf..7f3aa998e 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -176,6 +176,7 @@ private slots: | |||
| 176 | /// Called whenever a user selects a game in the game list widget. | 176 | /// Called whenever a user selects a game in the game list widget. |
| 177 | void OnGameListLoadFile(QString game_path); | 177 | void OnGameListLoadFile(QString game_path); |
| 178 | void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target); | 178 | void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target); |
| 179 | void OnTransferableShaderCacheOpenFile(u64 program_id); | ||
| 179 | void OnGameListDumpRomFS(u64 program_id, const std::string& game_path); | 180 | void OnGameListDumpRomFS(u64 program_id, const std::string& game_path); |
| 180 | void OnGameListCopyTID(u64 program_id); | 181 | void OnGameListCopyTID(u64 program_id); |
| 181 | void OnGameListNavigateToGamedbEntry(u64 program_id, | 182 | void OnGameListNavigateToGamedbEntry(u64 program_id, |