diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/CMakeLists.txt | 68 | ||||
| -rw-r--r-- | src/common/logging/filter.cpp | 4 | ||||
| -rw-r--r-- | src/common/logging/types.h | 4 | ||||
| -rw-r--r-- | src/common/scm_rev.cpp.in | 2 | ||||
| -rw-r--r-- | src/common/settings.cpp | 8 | ||||
| -rw-r--r-- | src/common/settings.h | 34 | ||||
| -rw-r--r-- | src/common/thread_worker.cpp | 58 | ||||
| -rw-r--r-- | src/common/thread_worker.h | 103 | ||||
| -rw-r--r-- | src/common/unique_function.h | 62 | ||||
| -rw-r--r-- | src/common/uuid.h | 5 |
10 files changed, 197 insertions, 151 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index a6fa9a85d..57922b51c 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -1,8 +1,3 @@ | |||
| 1 | # Add a custom command to generate a new shader_cache_version hash when any of the following files change | ||
| 2 | # NOTE: This is an approximation of what files affect shader generation, its possible something else | ||
| 3 | # could affect the result, but much more unlikely than the following files. Keeping a list of files | ||
| 4 | # like this allows for much better caching since it doesn't force the user to recompile binary shaders every update | ||
| 5 | set(VIDEO_CORE "${CMAKE_SOURCE_DIR}/src/video_core") | ||
| 6 | if (DEFINED ENV{AZURECIREPO}) | 1 | if (DEFINED ENV{AZURECIREPO}) |
| 7 | set(BUILD_REPOSITORY $ENV{AZURECIREPO}) | 2 | set(BUILD_REPOSITORY $ENV{AZURECIREPO}) |
| 8 | endif() | 3 | endif() |
| @@ -30,64 +25,7 @@ add_custom_command(OUTPUT scm_rev.cpp | |||
| 30 | -DGIT_EXECUTABLE=${GIT_EXECUTABLE} | 25 | -DGIT_EXECUTABLE=${GIT_EXECUTABLE} |
| 31 | -P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake | 26 | -P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake |
| 32 | DEPENDS | 27 | DEPENDS |
| 33 | # WARNING! It was too much work to try and make a common location for this list, | 28 | # Check that the scm_rev files haven't changed |
| 34 | # so if you need to change it, please update CMakeModules/GenerateSCMRev.cmake as well | ||
| 35 | "${VIDEO_CORE}/renderer_opengl/gl_arb_decompiler.cpp" | ||
| 36 | "${VIDEO_CORE}/renderer_opengl/gl_arb_decompiler.h" | ||
| 37 | "${VIDEO_CORE}/renderer_opengl/gl_shader_cache.cpp" | ||
| 38 | "${VIDEO_CORE}/renderer_opengl/gl_shader_cache.h" | ||
| 39 | "${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.cpp" | ||
| 40 | "${VIDEO_CORE}/renderer_opengl/gl_shader_decompiler.h" | ||
| 41 | "${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.cpp" | ||
| 42 | "${VIDEO_CORE}/renderer_opengl/gl_shader_disk_cache.h" | ||
| 43 | "${VIDEO_CORE}/shader/decode/arithmetic.cpp" | ||
| 44 | "${VIDEO_CORE}/shader/decode/arithmetic_half.cpp" | ||
| 45 | "${VIDEO_CORE}/shader/decode/arithmetic_half_immediate.cpp" | ||
| 46 | "${VIDEO_CORE}/shader/decode/arithmetic_immediate.cpp" | ||
| 47 | "${VIDEO_CORE}/shader/decode/arithmetic_integer.cpp" | ||
| 48 | "${VIDEO_CORE}/shader/decode/arithmetic_integer_immediate.cpp" | ||
| 49 | "${VIDEO_CORE}/shader/decode/bfe.cpp" | ||
| 50 | "${VIDEO_CORE}/shader/decode/bfi.cpp" | ||
| 51 | "${VIDEO_CORE}/shader/decode/conversion.cpp" | ||
| 52 | "${VIDEO_CORE}/shader/decode/ffma.cpp" | ||
| 53 | "${VIDEO_CORE}/shader/decode/float_set.cpp" | ||
| 54 | "${VIDEO_CORE}/shader/decode/float_set_predicate.cpp" | ||
| 55 | "${VIDEO_CORE}/shader/decode/half_set.cpp" | ||
| 56 | "${VIDEO_CORE}/shader/decode/half_set_predicate.cpp" | ||
| 57 | "${VIDEO_CORE}/shader/decode/hfma2.cpp" | ||
| 58 | "${VIDEO_CORE}/shader/decode/image.cpp" | ||
| 59 | "${VIDEO_CORE}/shader/decode/integer_set.cpp" | ||
| 60 | "${VIDEO_CORE}/shader/decode/integer_set_predicate.cpp" | ||
| 61 | "${VIDEO_CORE}/shader/decode/memory.cpp" | ||
| 62 | "${VIDEO_CORE}/shader/decode/texture.cpp" | ||
| 63 | "${VIDEO_CORE}/shader/decode/other.cpp" | ||
| 64 | "${VIDEO_CORE}/shader/decode/predicate_set_predicate.cpp" | ||
| 65 | "${VIDEO_CORE}/shader/decode/predicate_set_register.cpp" | ||
| 66 | "${VIDEO_CORE}/shader/decode/register_set_predicate.cpp" | ||
| 67 | "${VIDEO_CORE}/shader/decode/shift.cpp" | ||
| 68 | "${VIDEO_CORE}/shader/decode/video.cpp" | ||
| 69 | "${VIDEO_CORE}/shader/decode/warp.cpp" | ||
| 70 | "${VIDEO_CORE}/shader/decode/xmad.cpp" | ||
| 71 | "${VIDEO_CORE}/shader/ast.cpp" | ||
| 72 | "${VIDEO_CORE}/shader/ast.h" | ||
| 73 | "${VIDEO_CORE}/shader/compiler_settings.cpp" | ||
| 74 | "${VIDEO_CORE}/shader/compiler_settings.h" | ||
| 75 | "${VIDEO_CORE}/shader/control_flow.cpp" | ||
| 76 | "${VIDEO_CORE}/shader/control_flow.h" | ||
| 77 | "${VIDEO_CORE}/shader/decode.cpp" | ||
| 78 | "${VIDEO_CORE}/shader/expr.cpp" | ||
| 79 | "${VIDEO_CORE}/shader/expr.h" | ||
| 80 | "${VIDEO_CORE}/shader/node.h" | ||
| 81 | "${VIDEO_CORE}/shader/node_helper.cpp" | ||
| 82 | "${VIDEO_CORE}/shader/node_helper.h" | ||
| 83 | "${VIDEO_CORE}/shader/registry.cpp" | ||
| 84 | "${VIDEO_CORE}/shader/registry.h" | ||
| 85 | "${VIDEO_CORE}/shader/shader_ir.cpp" | ||
| 86 | "${VIDEO_CORE}/shader/shader_ir.h" | ||
| 87 | "${VIDEO_CORE}/shader/track.cpp" | ||
| 88 | "${VIDEO_CORE}/shader/transform_feedback.cpp" | ||
| 89 | "${VIDEO_CORE}/shader/transform_feedback.h" | ||
| 90 | # and also check that the scm_rev files haven't changed | ||
| 91 | "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" | 29 | "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" |
| 92 | "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.h" | 30 | "${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.h" |
| 93 | # technically we should regenerate if the git version changed, but its not worth the effort imo | 31 | # technically we should regenerate if the git version changed, but its not worth the effort imo |
| @@ -180,7 +118,6 @@ add_library(common STATIC | |||
| 180 | thread.cpp | 118 | thread.cpp |
| 181 | thread.h | 119 | thread.h |
| 182 | thread_queue_list.h | 120 | thread_queue_list.h |
| 183 | thread_worker.cpp | ||
| 184 | thread_worker.h | 121 | thread_worker.h |
| 185 | threadsafe_queue.h | 122 | threadsafe_queue.h |
| 186 | time_zone.cpp | 123 | time_zone.cpp |
| @@ -188,6 +125,7 @@ add_library(common STATIC | |||
| 188 | tiny_mt.h | 125 | tiny_mt.h |
| 189 | tree.h | 126 | tree.h |
| 190 | uint128.h | 127 | uint128.h |
| 128 | unique_function.h | ||
| 191 | uuid.cpp | 129 | uuid.cpp |
| 192 | uuid.h | 130 | uuid.h |
| 193 | vector_math.h | 131 | vector_math.h |
| @@ -231,7 +169,7 @@ endif() | |||
| 231 | 169 | ||
| 232 | create_target_directory_groups(common) | 170 | create_target_directory_groups(common) |
| 233 | 171 | ||
| 234 | target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile) | 172 | target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads) |
| 235 | target_link_libraries(common PRIVATE lz4::lz4 xbyak) | 173 | target_link_libraries(common PRIVATE lz4::lz4 xbyak) |
| 236 | if (MSVC) | 174 | if (MSVC) |
| 237 | target_link_libraries(common PRIVATE zstd::zstd) | 175 | target_link_libraries(common PRIVATE zstd::zstd) |
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 4f2cc29e1..f055f0e11 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp | |||
| @@ -144,6 +144,10 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { | |||
| 144 | SUB(Render, Software) \ | 144 | SUB(Render, Software) \ |
| 145 | SUB(Render, OpenGL) \ | 145 | SUB(Render, OpenGL) \ |
| 146 | SUB(Render, Vulkan) \ | 146 | SUB(Render, Vulkan) \ |
| 147 | CLS(Shader) \ | ||
| 148 | SUB(Shader, SPIRV) \ | ||
| 149 | SUB(Shader, GLASM) \ | ||
| 150 | SUB(Shader, GLSL) \ | ||
| 147 | CLS(Audio) \ | 151 | CLS(Audio) \ |
| 148 | SUB(Audio, DSP) \ | 152 | SUB(Audio, DSP) \ |
| 149 | SUB(Audio, Sink) \ | 153 | SUB(Audio, Sink) \ |
diff --git a/src/common/logging/types.h b/src/common/logging/types.h index 88b0e9c01..7ad0334fc 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h | |||
| @@ -114,6 +114,10 @@ enum class Class : u8 { | |||
| 114 | Render_Software, ///< Software renderer backend | 114 | Render_Software, ///< Software renderer backend |
| 115 | Render_OpenGL, ///< OpenGL backend | 115 | Render_OpenGL, ///< OpenGL backend |
| 116 | Render_Vulkan, ///< Vulkan backend | 116 | Render_Vulkan, ///< Vulkan backend |
| 117 | Shader, ///< Shader recompiler | ||
| 118 | Shader_SPIRV, ///< Shader SPIR-V code generation | ||
| 119 | Shader_GLASM, ///< Shader GLASM code generation | ||
| 120 | Shader_GLSL, ///< Shader GLSL code generation | ||
| 117 | Audio, ///< Audio emulation | 121 | Audio, ///< Audio emulation |
| 118 | Audio_DSP, ///< The HLE implementation of the DSP | 122 | Audio_DSP, ///< The HLE implementation of the DSP |
| 119 | Audio_Sink, ///< Emulator audio output backend | 123 | Audio_Sink, ///< Emulator audio output backend |
diff --git a/src/common/scm_rev.cpp.in b/src/common/scm_rev.cpp.in index 5f126f324..cc88994c6 100644 --- a/src/common/scm_rev.cpp.in +++ b/src/common/scm_rev.cpp.in | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #define BUILD_ID "@BUILD_ID@" | 14 | #define BUILD_ID "@BUILD_ID@" |
| 15 | #define TITLE_BAR_FORMAT_IDLE "@TITLE_BAR_FORMAT_IDLE@" | 15 | #define TITLE_BAR_FORMAT_IDLE "@TITLE_BAR_FORMAT_IDLE@" |
| 16 | #define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@" | 16 | #define TITLE_BAR_FORMAT_RUNNING "@TITLE_BAR_FORMAT_RUNNING@" |
| 17 | #define SHADER_CACHE_VERSION "@SHADER_CACHE_VERSION@" | ||
| 18 | 17 | ||
| 19 | namespace Common { | 18 | namespace Common { |
| 20 | 19 | ||
| @@ -28,7 +27,6 @@ const char g_build_version[] = BUILD_VERSION; | |||
| 28 | const char g_build_id[] = BUILD_ID; | 27 | const char g_build_id[] = BUILD_ID; |
| 29 | const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE; | 28 | const char g_title_bar_format_idle[] = TITLE_BAR_FORMAT_IDLE; |
| 30 | const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING; | 29 | const char g_title_bar_format_running[] = TITLE_BAR_FORMAT_RUNNING; |
| 31 | const char g_shader_cache_version[] = SHADER_CACHE_VERSION; | ||
| 32 | 30 | ||
| 33 | } // namespace | 31 | } // namespace |
| 34 | 32 | ||
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 0061e29cc..66268ea0f 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -57,7 +57,7 @@ void LogSettings() { | |||
| 57 | log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue()); | 57 | log_setting("Renderer_UseNvdecEmulation", values.use_nvdec_emulation.GetValue()); |
| 58 | log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue()); | 58 | log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue()); |
| 59 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); | 59 | log_setting("Renderer_UseVsync", values.use_vsync.GetValue()); |
| 60 | log_setting("Renderer_UseAssemblyShaders", values.use_assembly_shaders.GetValue()); | 60 | log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue()); |
| 61 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); | 61 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); |
| 62 | log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue()); | 62 | log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue()); |
| 63 | log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); | 63 | log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); |
| @@ -93,7 +93,7 @@ bool IsGPULevelHigh() { | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | bool IsFastmemEnabled() { | 95 | bool IsFastmemEnabled() { |
| 96 | if (values.cpu_accuracy.GetValue() == CPUAccuracy::DebugMode) { | 96 | if (values.cpu_debug_mode) { |
| 97 | return static_cast<bool>(values.cpuopt_fastmem); | 97 | return static_cast<bool>(values.cpuopt_fastmem); |
| 98 | } | 98 | } |
| 99 | return true; | 99 | return true; |
| @@ -103,7 +103,7 @@ float Volume() { | |||
| 103 | if (values.audio_muted) { | 103 | if (values.audio_muted) { |
| 104 | return 0.0f; | 104 | return 0.0f; |
| 105 | } | 105 | } |
| 106 | return values.volume.GetValue(); | 106 | return values.volume.GetValue() / 100.0f; |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void RestoreGlobalState(bool is_powered_on) { | 109 | void RestoreGlobalState(bool is_powered_on) { |
| @@ -140,7 +140,7 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 140 | values.use_nvdec_emulation.SetGlobal(true); | 140 | values.use_nvdec_emulation.SetGlobal(true); |
| 141 | values.accelerate_astc.SetGlobal(true); | 141 | values.accelerate_astc.SetGlobal(true); |
| 142 | values.use_vsync.SetGlobal(true); | 142 | values.use_vsync.SetGlobal(true); |
| 143 | values.use_assembly_shaders.SetGlobal(true); | 143 | values.shader_backend.SetGlobal(true); |
| 144 | values.use_asynchronous_shaders.SetGlobal(true); | 144 | values.use_asynchronous_shaders.SetGlobal(true); |
| 145 | values.use_fast_gpu_time.SetGlobal(true); | 145 | values.use_fast_gpu_time.SetGlobal(true); |
| 146 | values.use_caches_gc.SetGlobal(true); | 146 | values.use_caches_gc.SetGlobal(true); |
diff --git a/src/common/settings.h b/src/common/settings.h index bf83186f5..32dfb1d9f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -24,6 +24,12 @@ enum class RendererBackend : u32 { | |||
| 24 | Vulkan = 1, | 24 | Vulkan = 1, |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | enum class ShaderBackend : u32 { | ||
| 28 | GLSL = 0, | ||
| 29 | GLASM = 1, | ||
| 30 | SPIRV = 2, | ||
| 31 | }; | ||
| 32 | |||
| 27 | enum class GPUAccuracy : u32 { | 33 | enum class GPUAccuracy : u32 { |
| 28 | Normal = 0, | 34 | Normal = 0, |
| 29 | High = 1, | 35 | High = 1, |
| @@ -31,9 +37,9 @@ enum class GPUAccuracy : u32 { | |||
| 31 | }; | 37 | }; |
| 32 | 38 | ||
| 33 | enum class CPUAccuracy : u32 { | 39 | enum class CPUAccuracy : u32 { |
| 34 | Accurate = 0, | 40 | Auto = 0, |
| 35 | Unsafe = 1, | 41 | Accurate = 1, |
| 36 | DebugMode = 2, | 42 | Unsafe = 2, |
| 37 | }; | 43 | }; |
| 38 | 44 | ||
| 39 | /** The BasicSetting class is a simple resource manager. It defines a label and default value | 45 | /** The BasicSetting class is a simple resource manager. It defines a label and default value |
| @@ -278,13 +284,16 @@ struct Values { | |||
| 278 | BasicSetting<std::string> sink_id{"auto", "output_engine"}; | 284 | BasicSetting<std::string> sink_id{"auto", "output_engine"}; |
| 279 | BasicSetting<bool> audio_muted{false, "audio_muted"}; | 285 | BasicSetting<bool> audio_muted{false, "audio_muted"}; |
| 280 | Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; | 286 | Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; |
| 281 | Setting<float> volume{1.0f, "volume"}; | 287 | Setting<u8> volume{100, "volume"}; |
| 282 | 288 | ||
| 283 | // Core | 289 | // Core |
| 284 | Setting<bool> use_multi_core{true, "use_multi_core"}; | 290 | Setting<bool> use_multi_core{true, "use_multi_core"}; |
| 285 | 291 | ||
| 286 | // Cpu | 292 | // Cpu |
| 287 | Setting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Accurate, "cpu_accuracy"}; | 293 | Setting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, "cpu_accuracy"}; |
| 294 | // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 | ||
| 295 | BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; | ||
| 296 | BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; | ||
| 288 | 297 | ||
| 289 | BasicSetting<bool> cpuopt_page_tables{true, "cpuopt_page_tables"}; | 298 | BasicSetting<bool> cpuopt_page_tables{true, "cpuopt_page_tables"}; |
| 290 | BasicSetting<bool> cpuopt_block_linking{true, "cpuopt_block_linking"}; | 299 | BasicSetting<bool> cpuopt_block_linking{true, "cpuopt_block_linking"}; |
| @@ -305,6 +314,9 @@ struct Values { | |||
| 305 | // Renderer | 314 | // Renderer |
| 306 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; | 315 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; |
| 307 | BasicSetting<bool> renderer_debug{false, "debug"}; | 316 | BasicSetting<bool> renderer_debug{false, "debug"}; |
| 317 | BasicSetting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | ||
| 318 | BasicSetting<bool> disable_shader_loop_safety_checks{false, | ||
| 319 | "disable_shader_loop_safety_checks"}; | ||
| 308 | Setting<int> vulkan_device{0, "vulkan_device"}; | 320 | Setting<int> vulkan_device{0, "vulkan_device"}; |
| 309 | 321 | ||
| 310 | Setting<u16> resolution_factor{1, "resolution_factor"}; | 322 | Setting<u16> resolution_factor{1, "resolution_factor"}; |
| @@ -327,15 +339,15 @@ struct Values { | |||
| 327 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; | 339 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; |
| 328 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; | 340 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; |
| 329 | Setting<bool> use_vsync{true, "use_vsync"}; | 341 | Setting<bool> use_vsync{true, "use_vsync"}; |
| 330 | Setting<bool> disable_fps_limit{false, "disable_fps_limit"}; | 342 | BasicSetting<bool> disable_fps_limit{false, "disable_fps_limit"}; |
| 331 | Setting<bool> use_assembly_shaders{false, "use_assembly_shaders"}; | 343 | Setting<ShaderBackend> shader_backend{ShaderBackend::GLASM, "shader_backend"}; |
| 332 | Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; | 344 | Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; |
| 333 | Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; | 345 | Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; |
| 334 | Setting<bool> use_caches_gc{false, "use_caches_gc"}; | 346 | Setting<bool> use_caches_gc{false, "use_caches_gc"}; |
| 335 | 347 | ||
| 336 | Setting<float> bg_red{0.0f, "bg_red"}; | 348 | Setting<u8> bg_red{0, "bg_red"}; |
| 337 | Setting<float> bg_green{0.0f, "bg_green"}; | 349 | Setting<u8> bg_green{0, "bg_green"}; |
| 338 | Setting<float> bg_blue{0.0f, "bg_blue"}; | 350 | Setting<u8> bg_blue{0, "bg_blue"}; |
| 339 | 351 | ||
| 340 | // System | 352 | // System |
| 341 | Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"}; | 353 | Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"}; |
| @@ -365,7 +377,7 @@ struct Values { | |||
| 365 | "udp_input_servers"}; | 377 | "udp_input_servers"}; |
| 366 | 378 | ||
| 367 | BasicSetting<bool> mouse_panning{false, "mouse_panning"}; | 379 | BasicSetting<bool> mouse_panning{false, "mouse_panning"}; |
| 368 | BasicSetting<float> mouse_panning_sensitivity{1.0f, "mouse_panning_sensitivity"}; | 380 | BasicSetting<u8> mouse_panning_sensitivity{10, "mouse_panning_sensitivity"}; |
| 369 | BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; | 381 | BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; |
| 370 | std::string mouse_device; | 382 | std::string mouse_device; |
| 371 | MouseButtonsRaw mouse_buttons; | 383 | MouseButtonsRaw mouse_buttons; |
diff --git a/src/common/thread_worker.cpp b/src/common/thread_worker.cpp deleted file mode 100644 index 8f9bf447a..000000000 --- a/src/common/thread_worker.cpp +++ /dev/null | |||
| @@ -1,58 +0,0 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/thread.h" | ||
| 6 | #include "common/thread_worker.h" | ||
| 7 | |||
| 8 | namespace Common { | ||
| 9 | |||
| 10 | ThreadWorker::ThreadWorker(std::size_t num_workers, const std::string& name) { | ||
| 11 | for (std::size_t i = 0; i < num_workers; ++i) | ||
| 12 | threads.emplace_back([this, thread_name{std::string{name}}] { | ||
| 13 | Common::SetCurrentThreadName(thread_name.c_str()); | ||
| 14 | |||
| 15 | // Wait for first request | ||
| 16 | { | ||
| 17 | std::unique_lock lock{queue_mutex}; | ||
| 18 | condition.wait(lock, [this] { return stop || !requests.empty(); }); | ||
| 19 | } | ||
| 20 | |||
| 21 | while (true) { | ||
| 22 | std::function<void()> task; | ||
| 23 | |||
| 24 | { | ||
| 25 | std::unique_lock lock{queue_mutex}; | ||
| 26 | condition.wait(lock, [this] { return stop || !requests.empty(); }); | ||
| 27 | if (stop || requests.empty()) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | task = std::move(requests.front()); | ||
| 31 | requests.pop(); | ||
| 32 | } | ||
| 33 | |||
| 34 | task(); | ||
| 35 | } | ||
| 36 | }); | ||
| 37 | } | ||
| 38 | |||
| 39 | ThreadWorker::~ThreadWorker() { | ||
| 40 | { | ||
| 41 | std::unique_lock lock{queue_mutex}; | ||
| 42 | stop = true; | ||
| 43 | } | ||
| 44 | condition.notify_all(); | ||
| 45 | for (std::thread& thread : threads) { | ||
| 46 | thread.join(); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | void ThreadWorker::QueueWork(std::function<void()>&& work) { | ||
| 51 | { | ||
| 52 | std::unique_lock lock{queue_mutex}; | ||
| 53 | requests.emplace(work); | ||
| 54 | } | ||
| 55 | condition.notify_one(); | ||
| 56 | } | ||
| 57 | |||
| 58 | } // namespace Common | ||
diff --git a/src/common/thread_worker.h b/src/common/thread_worker.h index f1859971f..cd0017726 100644 --- a/src/common/thread_worker.h +++ b/src/common/thread_worker.h | |||
| @@ -5,26 +5,113 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <condition_variable> | ||
| 8 | #include <functional> | 9 | #include <functional> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 11 | #include <stop_token> | ||
| 10 | #include <string> | 12 | #include <string> |
| 13 | #include <thread> | ||
| 14 | #include <type_traits> | ||
| 11 | #include <vector> | 15 | #include <vector> |
| 12 | #include <queue> | 16 | #include <queue> |
| 13 | 17 | ||
| 18 | #include "common/thread.h" | ||
| 19 | #include "common/unique_function.h" | ||
| 20 | |||
| 14 | namespace Common { | 21 | namespace Common { |
| 15 | 22 | ||
| 16 | class ThreadWorker final { | 23 | template <class StateType = void> |
| 24 | class StatefulThreadWorker { | ||
| 25 | static constexpr bool with_state = !std::is_same_v<StateType, void>; | ||
| 26 | |||
| 27 | struct DummyCallable { | ||
| 28 | int operator()() const noexcept { | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | }; | ||
| 32 | |||
| 33 | using Task = | ||
| 34 | std::conditional_t<with_state, UniqueFunction<void, StateType*>, UniqueFunction<void>>; | ||
| 35 | using StateMaker = std::conditional_t<with_state, std::function<StateType()>, DummyCallable>; | ||
| 36 | |||
| 17 | public: | 37 | public: |
| 18 | explicit ThreadWorker(std::size_t num_workers, const std::string& name); | 38 | explicit StatefulThreadWorker(size_t num_workers, std::string name, StateMaker func = {}) |
| 19 | ~ThreadWorker(); | 39 | : workers_queued{num_workers}, thread_name{std::move(name)} { |
| 20 | void QueueWork(std::function<void()>&& work); | 40 | const auto lambda = [this, func](std::stop_token stop_token) { |
| 41 | Common::SetCurrentThreadName(thread_name.c_str()); | ||
| 42 | { | ||
| 43 | [[maybe_unused]] std::conditional_t<with_state, StateType, int> state{func()}; | ||
| 44 | while (!stop_token.stop_requested()) { | ||
| 45 | Task task; | ||
| 46 | { | ||
| 47 | std::unique_lock lock{queue_mutex}; | ||
| 48 | if (requests.empty()) { | ||
| 49 | wait_condition.notify_all(); | ||
| 50 | } | ||
| 51 | condition.wait(lock, stop_token, [this] { return !requests.empty(); }); | ||
| 52 | if (stop_token.stop_requested()) { | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | task = std::move(requests.front()); | ||
| 56 | requests.pop(); | ||
| 57 | } | ||
| 58 | if constexpr (with_state) { | ||
| 59 | task(&state); | ||
| 60 | } else { | ||
| 61 | task(); | ||
| 62 | } | ||
| 63 | ++work_done; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | ++workers_stopped; | ||
| 67 | wait_condition.notify_all(); | ||
| 68 | }; | ||
| 69 | threads.reserve(num_workers); | ||
| 70 | for (size_t i = 0; i < num_workers; ++i) { | ||
| 71 | threads.emplace_back(lambda); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | StatefulThreadWorker& operator=(const StatefulThreadWorker&) = delete; | ||
| 76 | StatefulThreadWorker(const StatefulThreadWorker&) = delete; | ||
| 77 | |||
| 78 | StatefulThreadWorker& operator=(StatefulThreadWorker&&) = delete; | ||
| 79 | StatefulThreadWorker(StatefulThreadWorker&&) = delete; | ||
| 80 | |||
| 81 | void QueueWork(Task work) { | ||
| 82 | { | ||
| 83 | std::unique_lock lock{queue_mutex}; | ||
| 84 | requests.emplace(std::move(work)); | ||
| 85 | ++work_scheduled; | ||
| 86 | } | ||
| 87 | condition.notify_one(); | ||
| 88 | } | ||
| 89 | |||
| 90 | void WaitForRequests(std::stop_token stop_token = {}) { | ||
| 91 | std::stop_callback callback(stop_token, [this] { | ||
| 92 | for (auto& thread : threads) { | ||
| 93 | thread.request_stop(); | ||
| 94 | } | ||
| 95 | }); | ||
| 96 | std::unique_lock lock{queue_mutex}; | ||
| 97 | wait_condition.wait(lock, [this] { | ||
| 98 | return workers_stopped >= workers_queued || work_done >= work_scheduled; | ||
| 99 | }); | ||
| 100 | } | ||
| 21 | 101 | ||
| 22 | private: | 102 | private: |
| 23 | std::vector<std::thread> threads; | 103 | std::queue<Task> requests; |
| 24 | std::queue<std::function<void()>> requests; | ||
| 25 | std::mutex queue_mutex; | 104 | std::mutex queue_mutex; |
| 26 | std::condition_variable condition; | 105 | std::condition_variable_any condition; |
| 27 | std::atomic_bool stop{}; | 106 | std::condition_variable wait_condition; |
| 107 | std::atomic<size_t> work_scheduled{}; | ||
| 108 | std::atomic<size_t> work_done{}; | ||
| 109 | std::atomic<size_t> workers_stopped{}; | ||
| 110 | std::atomic<size_t> workers_queued{}; | ||
| 111 | std::string thread_name; | ||
| 112 | std::vector<std::jthread> threads; | ||
| 28 | }; | 113 | }; |
| 29 | 114 | ||
| 115 | using ThreadWorker = StatefulThreadWorker<>; | ||
| 116 | |||
| 30 | } // namespace Common | 117 | } // namespace Common |
diff --git a/src/common/unique_function.h b/src/common/unique_function.h new file mode 100644 index 000000000..ca0559071 --- /dev/null +++ b/src/common/unique_function.h | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <utility> | ||
| 9 | |||
| 10 | namespace Common { | ||
| 11 | |||
| 12 | /// General purpose function wrapper similar to std::function. | ||
| 13 | /// Unlike std::function, the captured values don't have to be copyable. | ||
| 14 | /// This class can be moved but not copied. | ||
| 15 | template <typename ResultType, typename... Args> | ||
| 16 | class UniqueFunction { | ||
| 17 | class CallableBase { | ||
| 18 | public: | ||
| 19 | virtual ~CallableBase() = default; | ||
| 20 | virtual ResultType operator()(Args&&...) = 0; | ||
| 21 | }; | ||
| 22 | |||
| 23 | template <typename Functor> | ||
| 24 | class Callable final : public CallableBase { | ||
| 25 | public: | ||
| 26 | Callable(Functor&& functor_) : functor{std::move(functor_)} {} | ||
| 27 | ~Callable() override = default; | ||
| 28 | |||
| 29 | ResultType operator()(Args&&... args) override { | ||
| 30 | return functor(std::forward<Args>(args)...); | ||
| 31 | } | ||
| 32 | |||
| 33 | private: | ||
| 34 | Functor functor; | ||
| 35 | }; | ||
| 36 | |||
| 37 | public: | ||
| 38 | UniqueFunction() = default; | ||
| 39 | |||
| 40 | template <typename Functor> | ||
| 41 | UniqueFunction(Functor&& functor) | ||
| 42 | : callable{std::make_unique<Callable<Functor>>(std::move(functor))} {} | ||
| 43 | |||
| 44 | UniqueFunction& operator=(UniqueFunction&& rhs) noexcept = default; | ||
| 45 | UniqueFunction(UniqueFunction&& rhs) noexcept = default; | ||
| 46 | |||
| 47 | UniqueFunction& operator=(const UniqueFunction&) = delete; | ||
| 48 | UniqueFunction(const UniqueFunction&) = delete; | ||
| 49 | |||
| 50 | ResultType operator()(Args&&... args) const { | ||
| 51 | return (*callable)(std::forward<Args>(args)...); | ||
| 52 | } | ||
| 53 | |||
| 54 | explicit operator bool() const noexcept { | ||
| 55 | return static_cast<bool>(callable); | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | std::unique_ptr<CallableBase> callable; | ||
| 60 | }; | ||
| 61 | |||
| 62 | } // namespace Common | ||
diff --git a/src/common/uuid.h b/src/common/uuid.h index 2e7a18405..0ffa37e7c 100644 --- a/src/common/uuid.h +++ b/src/common/uuid.h | |||
| @@ -20,12 +20,11 @@ struct UUID { | |||
| 20 | constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} | 20 | constexpr explicit UUID(const u64 lo, const u64 hi) : uuid{{lo, hi}} {} |
| 21 | 21 | ||
| 22 | [[nodiscard]] constexpr explicit operator bool() const { | 22 | [[nodiscard]] constexpr explicit operator bool() const { |
| 23 | return uuid[0] != INVALID_UUID[0] && uuid[1] != INVALID_UUID[1]; | 23 | return uuid != INVALID_UUID; |
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | [[nodiscard]] constexpr bool operator==(const UUID& rhs) const { | 26 | [[nodiscard]] constexpr bool operator==(const UUID& rhs) const { |
| 27 | // TODO(DarkLordZach): Replace with uuid == rhs.uuid with C++20 | 27 | return uuid == rhs.uuid; |
| 28 | return uuid[0] == rhs.uuid[0] && uuid[1] == rhs.uuid[1]; | ||
| 29 | } | 28 | } |
| 30 | 29 | ||
| 31 | [[nodiscard]] constexpr bool operator!=(const UUID& rhs) const { | 30 | [[nodiscard]] constexpr bool operator!=(const UUID& rhs) const { |