diff options
Diffstat (limited to 'src')
213 files changed, 3722 insertions, 749 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0ac3d254e..140415474 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt | |||
| @@ -82,8 +82,9 @@ if (MSVC) | |||
| 82 | /wd4324 # 'struct_name': structure was padded due to __declspec(align()) | 82 | /wd4324 # 'struct_name': structure was padded due to __declspec(align()) |
| 83 | ) | 83 | ) |
| 84 | 84 | ||
| 85 | if (USE_CCACHE) | 85 | if (USE_CCACHE OR YUZU_USE_PRECOMPILED_HEADERS) |
| 86 | # when caching, we need to use /Z7 to downgrade debug info to use an older but more cachable format | 86 | # when caching, we need to use /Z7 to downgrade debug info to use an older but more cachable format |
| 87 | # Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21 | ||
| 87 | add_compile_options(/Z7) | 88 | add_compile_options(/Z7) |
| 88 | else() | 89 | else() |
| 89 | add_compile_options(/Zi) | 90 | add_compile_options(/Zi) |
| @@ -112,6 +113,8 @@ else() | |||
| 112 | 113 | ||
| 113 | $<$<CXX_COMPILER_ID:Clang>:-Wno-braced-scalar-init> | 114 | $<$<CXX_COMPILER_ID:Clang>:-Wno-braced-scalar-init> |
| 114 | $<$<CXX_COMPILER_ID:Clang>:-Wno-unused-private-field> | 115 | $<$<CXX_COMPILER_ID:Clang>:-Wno-unused-private-field> |
| 116 | $<$<CXX_COMPILER_ID:AppleClang>:-Wno-braced-scalar-init> | ||
| 117 | $<$<CXX_COMPILER_ID:AppleClang>:-Wno-unused-private-field> | ||
| 115 | ) | 118 | ) |
| 116 | 119 | ||
| 117 | if (ARCHITECTURE_x86_64) | 120 | if (ARCHITECTURE_x86_64) |
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index 75416c53a..420ba62e0 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt | |||
| @@ -31,6 +31,7 @@ add_library(audio_core STATIC | |||
| 31 | out/audio_out.h | 31 | out/audio_out.h |
| 32 | out/audio_out_system.cpp | 32 | out/audio_out_system.cpp |
| 33 | out/audio_out_system.h | 33 | out/audio_out_system.h |
| 34 | precompiled_headers.h | ||
| 34 | renderer/adsp/adsp.cpp | 35 | renderer/adsp/adsp.cpp |
| 35 | renderer/adsp/adsp.h | 36 | renderer/adsp/adsp.h |
| 36 | renderer/adsp/audio_renderer.cpp | 37 | renderer/adsp/audio_renderer.cpp |
| @@ -218,18 +219,18 @@ endif() | |||
| 218 | 219 | ||
| 219 | target_link_libraries(audio_core PUBLIC common core) | 220 | target_link_libraries(audio_core PUBLIC common core) |
| 220 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) | 221 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) |
| 221 | target_link_libraries(audio_core PRIVATE dynarmic) | 222 | target_link_libraries(audio_core PRIVATE dynarmic::dynarmic) |
| 222 | endif() | 223 | endif() |
| 223 | 224 | ||
| 224 | if(ENABLE_CUBEB) | 225 | if(ENABLE_CUBEB) |
| 225 | target_link_libraries(audio_core PRIVATE cubeb) | 226 | target_link_libraries(audio_core PRIVATE cubeb::cubeb) |
| 226 | target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1) | 227 | target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1) |
| 227 | endif() | 228 | endif() |
| 228 | if(ENABLE_SDL2) | 229 | if(ENABLE_SDL2) |
| 229 | if (YUZU_USE_EXTERNAL_SDL2) | 230 | target_link_libraries(audio_core PRIVATE SDL2::SDL2) |
| 230 | target_link_libraries(audio_core PRIVATE SDL2-static) | ||
| 231 | else() | ||
| 232 | target_link_libraries(audio_core PRIVATE SDL2) | ||
| 233 | endif() | ||
| 234 | target_compile_definitions(audio_core PRIVATE HAVE_SDL2) | 231 | target_compile_definitions(audio_core PRIVATE HAVE_SDL2) |
| 235 | endif() | 232 | endif() |
| 233 | |||
| 234 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 235 | target_precompile_headers(audio_core PRIVATE precompiled_headers.h) | ||
| 236 | endif() | ||
diff --git a/src/audio_core/audio_event.cpp b/src/audio_core/audio_event.cpp index 424049c7a..d15568e1f 100644 --- a/src/audio_core/audio_event.cpp +++ b/src/audio_core/audio_event.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include "audio_core/audio_event.h" | 4 | #include "audio_core/audio_event.h" |
| 5 | #include "common/assert.h" | 5 | #include "common/assert.h" |
| 6 | #include "common/polyfill_ranges.h" | ||
| 6 | 7 | ||
| 7 | namespace AudioCore { | 8 | namespace AudioCore { |
| 8 | 9 | ||
diff --git a/src/audio_core/audio_manager.h b/src/audio_core/audio_manager.h index abf077de4..02270242a 100644 --- a/src/audio_core/audio_manager.h +++ b/src/audio_core/audio_manager.h | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <thread> | 10 | #include <thread> |
| 11 | 11 | ||
| 12 | #include "common/polyfill_thread.h" | ||
| 13 | |||
| 12 | #include "audio_core/audio_event.h" | 14 | #include "audio_core/audio_event.h" |
| 13 | 15 | ||
| 14 | union Result; | 16 | union Result; |
diff --git a/src/audio_core/audio_render_manager.h b/src/audio_core/audio_render_manager.h index bf4837190..fffa5944d 100644 --- a/src/audio_core/audio_render_manager.h +++ b/src/audio_core/audio_render_manager.h | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <mutex> | 8 | #include <mutex> |
| 9 | 9 | ||
| 10 | #include "common/polyfill_thread.h" | ||
| 11 | |||
| 10 | #include "audio_core/common/common.h" | 12 | #include "audio_core/common/common.h" |
| 11 | #include "audio_core/renderer/system_manager.h" | 13 | #include "audio_core/renderer/system_manager.h" |
| 12 | #include "core/hle/service/audio/errors.h" | 14 | #include "core/hle/service/audio/errors.h" |
diff --git a/src/audio_core/common/feature_support.h b/src/audio_core/common/feature_support.h index 55c9e690d..e71905ae8 100644 --- a/src/audio_core/common/feature_support.h +++ b/src/audio_core/common/feature_support.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 11 | #include "common/common_funcs.h" | 11 | #include "common/common_funcs.h" |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "common/polyfill_ranges.h" | ||
| 13 | 14 | ||
| 14 | namespace AudioCore { | 15 | namespace AudioCore { |
| 15 | constexpr u32 CurrentRevision = 11; | 16 | constexpr u32 CurrentRevision = 11; |
diff --git a/src/audio_core/precompiled_headers.h b/src/audio_core/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/audio_core/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp index c4bf3943a..2187d8a65 100644 --- a/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp +++ b/src/audio_core/renderer/command/effect/i3dl2_reverb.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "audio_core/renderer/adsp/command_list_processor.h" | 6 | #include "audio_core/renderer/adsp/command_list_processor.h" |
| 7 | #include "audio_core/renderer/command/effect/i3dl2_reverb.h" | 7 | #include "audio_core/renderer/command/effect/i3dl2_reverb.h" |
| 8 | #include "common/polyfill_ranges.h" | ||
| 8 | 9 | ||
| 9 | namespace AudioCore::AudioRenderer { | 10 | namespace AudioCore::AudioRenderer { |
| 10 | 11 | ||
diff --git a/src/audio_core/renderer/command/effect/reverb.cpp b/src/audio_core/renderer/command/effect/reverb.cpp index fe2b1eb43..427489214 100644 --- a/src/audio_core/renderer/command/effect/reverb.cpp +++ b/src/audio_core/renderer/command/effect/reverb.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include "audio_core/renderer/adsp/command_list_processor.h" | 7 | #include "audio_core/renderer/adsp/command_list_processor.h" |
| 8 | #include "audio_core/renderer/command/effect/reverb.h" | 8 | #include "audio_core/renderer/command/effect/reverb.h" |
| 9 | #include "common/polyfill_ranges.h" | ||
| 9 | 10 | ||
| 10 | namespace AudioCore::AudioRenderer { | 11 | namespace AudioCore::AudioRenderer { |
| 11 | 12 | ||
diff --git a/src/audio_core/renderer/mix/mix_context.cpp b/src/audio_core/renderer/mix/mix_context.cpp index 2427c83ed..35b748ede 100644 --- a/src/audio_core/renderer/mix/mix_context.cpp +++ b/src/audio_core/renderer/mix/mix_context.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "audio_core/renderer/mix/mix_context.h" | 6 | #include "audio_core/renderer/mix/mix_context.h" |
| 7 | #include "audio_core/renderer/splitter/splitter_context.h" | 7 | #include "audio_core/renderer/splitter/splitter_context.h" |
| 8 | #include "common/polyfill_ranges.h" | ||
| 8 | 9 | ||
| 9 | namespace AudioCore::AudioRenderer { | 10 | namespace AudioCore::AudioRenderer { |
| 10 | 11 | ||
diff --git a/src/audio_core/renderer/voice/voice_context.cpp b/src/audio_core/renderer/voice/voice_context.cpp index a501a677d..16a3e839d 100644 --- a/src/audio_core/renderer/voice/voice_context.cpp +++ b/src/audio_core/renderer/voice/voice_context.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <ranges> | 4 | #include <ranges> |
| 5 | 5 | ||
| 6 | #include "audio_core/renderer/voice/voice_context.h" | 6 | #include "audio_core/renderer/voice/voice_context.h" |
| 7 | #include "common/polyfill_ranges.h" | ||
| 7 | 8 | ||
| 8 | namespace AudioCore::AudioRenderer { | 9 | namespace AudioCore::AudioRenderer { |
| 9 | 10 | ||
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp index 67e194e3c..06c2a876e 100644 --- a/src/audio_core/sink/sink_stream.cpp +++ b/src/audio_core/sink/sink_stream.cpp | |||
| @@ -170,8 +170,8 @@ void SinkStream::ProcessAudioIn(std::span<const s16> input_buffer, std::size_t n | |||
| 170 | 170 | ||
| 171 | // Get the minimum frames available between the currently playing buffer, and the | 171 | // Get the minimum frames available between the currently playing buffer, and the |
| 172 | // amount we have left to fill | 172 | // amount we have left to fill |
| 173 | size_t frames_available{std::min(playing_buffer.frames - playing_buffer.frames_played, | 173 | size_t frames_available{std::min<u64>(playing_buffer.frames - playing_buffer.frames_played, |
| 174 | num_frames - frames_written)}; | 174 | num_frames - frames_written)}; |
| 175 | 175 | ||
| 176 | samples_buffer.Push(&input_buffer[frames_written * frame_size], | 176 | samples_buffer.Push(&input_buffer[frames_written * frame_size], |
| 177 | frames_available * frame_size); | 177 | frames_available * frame_size); |
| @@ -241,8 +241,8 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz | |||
| 241 | 241 | ||
| 242 | // Get the minimum frames available between the currently playing buffer, and the | 242 | // Get the minimum frames available between the currently playing buffer, and the |
| 243 | // amount we have left to fill | 243 | // amount we have left to fill |
| 244 | size_t frames_available{std::min(playing_buffer.frames - playing_buffer.frames_played, | 244 | size_t frames_available{std::min<u64>(playing_buffer.frames - playing_buffer.frames_played, |
| 245 | num_frames - frames_written)}; | 245 | num_frames - frames_written)}; |
| 246 | 246 | ||
| 247 | samples_buffer.Pop(&output_buffer[frames_written * frame_size], | 247 | samples_buffer.Pop(&output_buffer[frames_written * frame_size], |
| 248 | frames_available * frame_size); | 248 | frames_available * frame_size); |
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index b7c15c191..6bdffcb7a 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -37,6 +37,7 @@ add_library(common STATIC | |||
| 37 | cache_management.cpp | 37 | cache_management.cpp |
| 38 | cache_management.h | 38 | cache_management.h |
| 39 | common_funcs.h | 39 | common_funcs.h |
| 40 | common_precompiled_headers.h | ||
| 40 | common_types.h | 41 | common_types.h |
| 41 | concepts.h | 42 | concepts.h |
| 42 | div_ceil.h | 43 | div_ceil.h |
| @@ -95,6 +96,7 @@ add_library(common STATIC | |||
| 95 | param_package.h | 96 | param_package.h |
| 96 | parent_of_member.h | 97 | parent_of_member.h |
| 97 | point.h | 98 | point.h |
| 99 | precompiled_headers.h | ||
| 98 | quaternion.h | 100 | quaternion.h |
| 99 | reader_writer_queue.h | 101 | reader_writer_queue.h |
| 100 | ring_buffer.h | 102 | ring_buffer.h |
| @@ -147,7 +149,7 @@ if(ARCHITECTURE_x86_64) | |||
| 147 | x64/xbyak_abi.h | 149 | x64/xbyak_abi.h |
| 148 | x64/xbyak_util.h | 150 | x64/xbyak_util.h |
| 149 | ) | 151 | ) |
| 150 | target_link_libraries(common PRIVATE xbyak) | 152 | target_link_libraries(common PRIVATE xbyak::xbyak) |
| 151 | endif() | 153 | endif() |
| 152 | 154 | ||
| 153 | if (MSVC) | 155 | if (MSVC) |
| @@ -172,14 +174,8 @@ endif() | |||
| 172 | create_target_directory_groups(common) | 174 | create_target_directory_groups(common) |
| 173 | 175 | ||
| 174 | target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads) | 176 | target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads) |
| 175 | if (TARGET lz4::lz4) | 177 | target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd) |
| 176 | target_link_libraries(common PRIVATE lz4::lz4) | 178 | |
| 177 | else() | 179 | if (YUZU_USE_PRECOMPILED_HEADERS) |
| 178 | target_link_libraries(common PRIVATE LZ4::lz4_shared) | 180 | target_precompile_headers(common PRIVATE precompiled_headers.h) |
| 179 | endif() | ||
| 180 | if (TARGET zstd::zstd) | ||
| 181 | target_link_libraries(common PRIVATE zstd::zstd) | ||
| 182 | else() | ||
| 183 | target_link_libraries(common PRIVATE | ||
| 184 | $<IF:$<TARGET_EXISTS:zstd::libzstd_shared>,zstd::libzstd_shared,zstd::libzstd_static>) | ||
| 185 | endif() | 181 | endif() |
diff --git a/src/common/common_precompiled_headers.h b/src/common/common_precompiled_headers.h new file mode 100644 index 000000000..be7e5b5f9 --- /dev/null +++ b/src/common/common_precompiled_headers.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <algorithm> | ||
| 7 | #include <array> | ||
| 8 | #include <chrono> | ||
| 9 | #include <memory> | ||
| 10 | |||
| 11 | #include <fmt/format.h> | ||
| 12 | |||
| 13 | #include "common/assert.h" | ||
| 14 | #include "common/common_types.h" | ||
diff --git a/src/common/fs/file.cpp b/src/common/fs/file.cpp index fa8422c41..656b03cc5 100644 --- a/src/common/fs/file.cpp +++ b/src/common/fs/file.cpp | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <vector> | ||
| 5 | |||
| 4 | #include "common/fs/file.h" | 6 | #include "common/fs/file.h" |
| 5 | #include "common/fs/fs.h" | 7 | #include "common/fs/fs.h" |
| 6 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp index eb4ac1deb..813a713c3 100644 --- a/src/common/fs/fs_util.cpp +++ b/src/common/fs/fs_util.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | 5 | ||
| 6 | #include "common/fs/fs_util.h" | 6 | #include "common/fs/fs_util.h" |
| 7 | #include "common/polyfill_ranges.h" | ||
| 7 | 8 | ||
| 8 | namespace Common::FS { | 9 | namespace Common::FS { |
| 9 | 10 | ||
diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index 1074f2421..defa3e918 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | #include <sstream> | ||
| 5 | #include <unordered_map> | 6 | #include <unordered_map> |
| 6 | 7 | ||
| 7 | #include "common/fs/fs.h" | 8 | #include "common/fs/fs.h" |
diff --git a/src/common/input.h b/src/common/input.h index 449e0193f..fc14fd7bf 100644 --- a/src/common/input.h +++ b/src/common/input.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | #include <utility> | 10 | #include <utility> |
| 11 | #include <vector> | ||
| 11 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 12 | #include "common/param_package.h" | 13 | #include "common/param_package.h" |
| 13 | #include "common/uuid.h" | 14 | #include "common/uuid.h" |
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 15d92505e..2a3bded40 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | #include <atomic> | 4 | #include <atomic> |
| 5 | #include <chrono> | 5 | #include <chrono> |
| 6 | #include <climits> | 6 | #include <climits> |
| 7 | #include <stop_token> | ||
| 8 | #include <thread> | 7 | #include <thread> |
| 9 | 8 | ||
| 10 | #include <fmt/format.h> | 9 | #include <fmt/format.h> |
| @@ -18,6 +17,7 @@ | |||
| 18 | #include "common/fs/fs_paths.h" | 17 | #include "common/fs/fs_paths.h" |
| 19 | #include "common/fs/path_util.h" | 18 | #include "common/fs/path_util.h" |
| 20 | #include "common/literals.h" | 19 | #include "common/literals.h" |
| 20 | #include "common/polyfill_thread.h" | ||
| 21 | #include "common/thread.h" | 21 | #include "common/thread.h" |
| 22 | 22 | ||
| 23 | #include "common/logging/backend.h" | 23 | #include "common/logging/backend.h" |
diff --git a/src/common/polyfill_ranges.h b/src/common/polyfill_ranges.h new file mode 100644 index 000000000..ca44bfaef --- /dev/null +++ b/src/common/polyfill_ranges.h | |||
| @@ -0,0 +1,530 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | // | ||
| 5 | // TODO: remove this file when ranges are supported by all compilation targets | ||
| 6 | // | ||
| 7 | |||
| 8 | #pragma once | ||
| 9 | |||
| 10 | #include <algorithm> | ||
| 11 | #include <utility> | ||
| 12 | #include <version> | ||
| 13 | |||
| 14 | #ifndef __cpp_lib_ranges | ||
| 15 | |||
| 16 | namespace std { | ||
| 17 | namespace ranges { | ||
| 18 | |||
| 19 | template <typename T> | ||
| 20 | concept range = requires(T& t) { | ||
| 21 | begin(t); | ||
| 22 | end(t); | ||
| 23 | }; | ||
| 24 | |||
| 25 | template <typename T> | ||
| 26 | concept input_range = range<T>; | ||
| 27 | |||
| 28 | template <typename T> | ||
| 29 | concept output_range = range<T>; | ||
| 30 | |||
| 31 | template <range R> | ||
| 32 | using range_difference_t = ptrdiff_t; | ||
| 33 | |||
| 34 | // | ||
| 35 | // find, find_if, find_if_not | ||
| 36 | // | ||
| 37 | |||
| 38 | struct find_fn { | ||
| 39 | template <typename Iterator, typename T, typename Proj = std::identity> | ||
| 40 | constexpr Iterator operator()(Iterator first, Iterator last, const T& value, | ||
| 41 | Proj proj = {}) const { | ||
| 42 | for (; first != last; ++first) { | ||
| 43 | if (std::invoke(proj, *first) == value) { | ||
| 44 | return first; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | return first; | ||
| 48 | } | ||
| 49 | |||
| 50 | template <ranges::input_range R, typename T, typename Proj = std::identity> | ||
| 51 | constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Proj proj = {}) const { | ||
| 52 | return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj)); | ||
| 53 | } | ||
| 54 | }; | ||
| 55 | |||
| 56 | struct find_if_fn { | ||
| 57 | template <typename Iterator, typename Proj = std::identity, typename Pred> | ||
| 58 | constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { | ||
| 59 | for (; first != last; ++first) { | ||
| 60 | if (std::invoke(pred, std::invoke(proj, *first))) { | ||
| 61 | return first; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | return first; | ||
| 65 | } | ||
| 66 | |||
| 67 | template <ranges::input_range R, typename Proj = std::identity, typename Pred> | ||
| 68 | constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const { | ||
| 69 | return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); | ||
| 70 | } | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct find_if_not_fn { | ||
| 74 | template <typename Iterator, typename Proj = std::identity, typename Pred> | ||
| 75 | constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { | ||
| 76 | for (; first != last; ++first) { | ||
| 77 | if (!std::invoke(pred, std::invoke(proj, *first))) { | ||
| 78 | return first; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | return first; | ||
| 82 | } | ||
| 83 | |||
| 84 | template <ranges::input_range R, typename Proj = std::identity, typename Pred> | ||
| 85 | constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const { | ||
| 86 | return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); | ||
| 87 | } | ||
| 88 | }; | ||
| 89 | |||
| 90 | inline constexpr find_fn find; | ||
| 91 | inline constexpr find_if_fn find_if; | ||
| 92 | inline constexpr find_if_not_fn find_if_not; | ||
| 93 | |||
| 94 | // | ||
| 95 | // any_of, all_of, none_of | ||
| 96 | // | ||
| 97 | |||
| 98 | struct all_of_fn { | ||
| 99 | template <typename Iterator, typename Proj = std::identity, typename Pred> | ||
| 100 | constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { | ||
| 101 | return ranges::find_if_not(first, last, std::ref(pred), std::ref(proj)) == last; | ||
| 102 | } | ||
| 103 | |||
| 104 | template <ranges::input_range R, typename Proj = std::identity, typename Pred> | ||
| 105 | constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const { | ||
| 106 | return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); | ||
| 107 | } | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct any_of_fn { | ||
| 111 | template <typename Iterator, typename Proj = std::identity, typename Pred> | ||
| 112 | constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { | ||
| 113 | return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) != last; | ||
| 114 | } | ||
| 115 | |||
| 116 | template <ranges::input_range R, typename Proj = std::identity, typename Pred> | ||
| 117 | constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const { | ||
| 118 | return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); | ||
| 119 | } | ||
| 120 | }; | ||
| 121 | |||
| 122 | struct none_of_fn { | ||
| 123 | template <typename Iterator, typename Proj = std::identity, typename Pred> | ||
| 124 | constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { | ||
| 125 | return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) == last; | ||
| 126 | } | ||
| 127 | |||
| 128 | template <ranges::input_range R, typename Proj = std::identity, typename Pred> | ||
| 129 | constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const { | ||
| 130 | return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); | ||
| 131 | } | ||
| 132 | }; | ||
| 133 | |||
| 134 | inline constexpr any_of_fn any_of; | ||
| 135 | inline constexpr all_of_fn all_of; | ||
| 136 | inline constexpr none_of_fn none_of; | ||
| 137 | |||
| 138 | // | ||
| 139 | // count, count_if | ||
| 140 | // | ||
| 141 | |||
| 142 | struct count_fn { | ||
| 143 | template <typename Iterator, typename T, typename Proj = std::identity> | ||
| 144 | constexpr ptrdiff_t operator()(Iterator first, Iterator last, const T& value, | ||
| 145 | Proj proj = {}) const { | ||
| 146 | ptrdiff_t counter = 0; | ||
| 147 | for (; first != last; ++first) | ||
| 148 | if (std::invoke(proj, *first) == value) | ||
| 149 | ++counter; | ||
| 150 | return counter; | ||
| 151 | } | ||
| 152 | |||
| 153 | template <ranges::input_range R, typename T, typename Proj = std::identity> | ||
| 154 | constexpr ptrdiff_t operator()(R&& r, const T& value, Proj proj = {}) const { | ||
| 155 | return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj)); | ||
| 156 | } | ||
| 157 | }; | ||
| 158 | |||
| 159 | struct count_if_fn { | ||
| 160 | template <typename Iterator, typename Proj = std::identity, typename Pred> | ||
| 161 | constexpr ptrdiff_t operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const { | ||
| 162 | ptrdiff_t counter = 0; | ||
| 163 | for (; first != last; ++first) | ||
| 164 | if (std::invoke(pred, std::invoke(proj, *first))) | ||
| 165 | ++counter; | ||
| 166 | return counter; | ||
| 167 | } | ||
| 168 | |||
| 169 | template <ranges::input_range R, typename Proj = std::identity, typename Pred> | ||
| 170 | constexpr ptrdiff_t operator()(R&& r, Pred pred, Proj proj = {}) const { | ||
| 171 | return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); | ||
| 172 | } | ||
| 173 | }; | ||
| 174 | |||
| 175 | inline constexpr count_fn count; | ||
| 176 | inline constexpr count_if_fn count_if; | ||
| 177 | |||
| 178 | // | ||
| 179 | // transform | ||
| 180 | // | ||
| 181 | |||
| 182 | struct transform_fn { | ||
| 183 | template <typename InputIterator, typename OutputIterator, typename F, | ||
| 184 | typename Proj = std::identity> | ||
| 185 | constexpr void operator()(InputIterator first1, InputIterator last1, OutputIterator result, | ||
| 186 | F op, Proj proj = {}) const { | ||
| 187 | for (; first1 != last1; ++first1, (void)++result) { | ||
| 188 | *result = std::invoke(op, std::invoke(proj, *first1)); | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | template <ranges::input_range R, typename OutputIterator, typename F, | ||
| 193 | typename Proj = std::identity> | ||
| 194 | constexpr void operator()(R&& r, OutputIterator result, F op, Proj proj = {}) const { | ||
| 195 | return operator()(ranges::begin(r), ranges::end(r), result, std::ref(op), std::ref(proj)); | ||
| 196 | } | ||
| 197 | }; | ||
| 198 | |||
| 199 | inline constexpr transform_fn transform; | ||
| 200 | |||
| 201 | // | ||
| 202 | // sort | ||
| 203 | // | ||
| 204 | |||
| 205 | struct sort_fn { | ||
| 206 | template <typename Iterator, typename Comp = ranges::less, typename Proj = std::identity> | ||
| 207 | constexpr void operator()(Iterator first, Iterator last, Comp comp = {}, Proj proj = {}) const { | ||
| 208 | if (first == last) | ||
| 209 | return; | ||
| 210 | |||
| 211 | Iterator last_iter = ranges::next(first, last); | ||
| 212 | std::sort(first, last_iter, | ||
| 213 | [&](auto& lhs, auto& rhs) { return comp(proj(lhs), proj(rhs)); }); | ||
| 214 | } | ||
| 215 | |||
| 216 | template <ranges::input_range R, typename Comp = ranges::less, typename Proj = std::identity> | ||
| 217 | constexpr void operator()(R&& r, Comp comp = {}, Proj proj = {}) const { | ||
| 218 | return operator()(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj)); | ||
| 219 | } | ||
| 220 | }; | ||
| 221 | |||
| 222 | inline constexpr sort_fn sort; | ||
| 223 | |||
| 224 | // | ||
| 225 | // fill | ||
| 226 | // | ||
| 227 | |||
| 228 | struct fill_fn { | ||
| 229 | template <typename T, typename OutputIterator> | ||
| 230 | constexpr OutputIterator operator()(OutputIterator first, OutputIterator last, | ||
| 231 | const T& value) const { | ||
| 232 | while (first != last) { | ||
| 233 | *first++ = value; | ||
| 234 | } | ||
| 235 | |||
| 236 | return first; | ||
| 237 | } | ||
| 238 | |||
| 239 | template <typename T, ranges::output_range R> | ||
| 240 | constexpr ranges::iterator_t<R> operator()(R&& r, const T& value) const { | ||
| 241 | return operator()(ranges::begin(r), ranges::end(r), value); | ||
| 242 | } | ||
| 243 | }; | ||
| 244 | |||
| 245 | inline constexpr fill_fn fill; | ||
| 246 | |||
| 247 | // | ||
| 248 | // for_each | ||
| 249 | // | ||
| 250 | |||
| 251 | struct for_each_fn { | ||
| 252 | template <typename Iterator, typename Proj = std::identity, typename Fun> | ||
| 253 | constexpr void operator()(Iterator first, Iterator last, Fun f, Proj proj = {}) const { | ||
| 254 | for (; first != last; ++first) { | ||
| 255 | std::invoke(f, std::invoke(proj, *first)); | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | template <ranges::input_range R, typename Proj = std::identity, typename Fun> | ||
| 260 | constexpr void operator()(R&& r, Fun f, Proj proj = {}) const { | ||
| 261 | return operator()(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj)); | ||
| 262 | } | ||
| 263 | }; | ||
| 264 | |||
| 265 | inline constexpr for_each_fn for_each; | ||
| 266 | |||
| 267 | // | ||
| 268 | // min_element, max_element | ||
| 269 | // | ||
| 270 | |||
| 271 | struct min_element_fn { | ||
| 272 | template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less> | ||
| 273 | constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {}, | ||
| 274 | Proj proj = {}) const { | ||
| 275 | if (first == last) { | ||
| 276 | return last; | ||
| 277 | } | ||
| 278 | |||
| 279 | auto smallest = first; | ||
| 280 | ++first; | ||
| 281 | for (; first != last; ++first) { | ||
| 282 | if (!std::invoke(comp, std::invoke(proj, *smallest), std::invoke(proj, *first))) { | ||
| 283 | smallest = first; | ||
| 284 | } | ||
| 285 | } | ||
| 286 | return smallest; | ||
| 287 | } | ||
| 288 | |||
| 289 | template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less> | ||
| 290 | constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const { | ||
| 291 | return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj)); | ||
| 292 | } | ||
| 293 | }; | ||
| 294 | |||
| 295 | struct max_element_fn { | ||
| 296 | template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less> | ||
| 297 | constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {}, | ||
| 298 | Proj proj = {}) const { | ||
| 299 | if (first == last) { | ||
| 300 | return last; | ||
| 301 | } | ||
| 302 | |||
| 303 | auto largest = first; | ||
| 304 | ++first; | ||
| 305 | for (; first != last; ++first) { | ||
| 306 | if (std::invoke(comp, std::invoke(proj, *largest), std::invoke(proj, *first))) { | ||
| 307 | largest = first; | ||
| 308 | } | ||
| 309 | } | ||
| 310 | return largest; | ||
| 311 | } | ||
| 312 | |||
| 313 | template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less> | ||
| 314 | constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const { | ||
| 315 | return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj)); | ||
| 316 | } | ||
| 317 | }; | ||
| 318 | |||
| 319 | inline constexpr min_element_fn min_element; | ||
| 320 | inline constexpr max_element_fn max_element; | ||
| 321 | |||
| 322 | // | ||
| 323 | // replace, replace_if | ||
| 324 | // | ||
| 325 | |||
| 326 | struct replace_fn { | ||
| 327 | template <typename Iterator, typename T1, typename T2, typename Proj = std::identity> | ||
| 328 | constexpr Iterator operator()(Iterator first, Iterator last, const T1& old_value, | ||
| 329 | const T2& new_value, Proj proj = {}) const { | ||
| 330 | for (; first != last; ++first) { | ||
| 331 | if (old_value == std::invoke(proj, *first)) { | ||
| 332 | *first = new_value; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | return first; | ||
| 336 | } | ||
| 337 | |||
| 338 | template <ranges::input_range R, typename T1, typename T2, typename Proj = std::identity> | ||
| 339 | constexpr ranges::iterator_t<R> operator()(R&& r, const T1& old_value, const T2& new_value, | ||
| 340 | Proj proj = {}) const { | ||
| 341 | return operator()(ranges::begin(r), ranges::end(r), old_value, new_value, std::move(proj)); | ||
| 342 | } | ||
| 343 | }; | ||
| 344 | |||
| 345 | struct replace_if_fn { | ||
| 346 | template <typename Iterator, typename T, typename Proj = std::identity, typename Pred> | ||
| 347 | constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, const T& new_value, | ||
| 348 | Proj proj = {}) const { | ||
| 349 | for (; first != last; ++first) { | ||
| 350 | if (!!std::invoke(pred, std::invoke(proj, *first))) { | ||
| 351 | *first = new_value; | ||
| 352 | } | ||
| 353 | } | ||
| 354 | return std::move(first); | ||
| 355 | } | ||
| 356 | |||
| 357 | template <ranges::input_range R, typename T, typename Proj = std::identity, typename Pred> | ||
| 358 | constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, const T& new_value, | ||
| 359 | Proj proj = {}) const { | ||
| 360 | return operator()(ranges::begin(r), ranges::end(r), std::move(pred), new_value, | ||
| 361 | std::move(proj)); | ||
| 362 | } | ||
| 363 | }; | ||
| 364 | |||
| 365 | inline constexpr replace_fn replace; | ||
| 366 | inline constexpr replace_if_fn replace_if; | ||
| 367 | |||
| 368 | // | ||
| 369 | // copy, copy_if | ||
| 370 | // | ||
| 371 | |||
| 372 | struct copy_fn { | ||
| 373 | template <typename InputIterator, typename OutputIterator> | ||
| 374 | constexpr void operator()(InputIterator first, InputIterator last, | ||
| 375 | OutputIterator result) const { | ||
| 376 | for (; first != last; ++first, (void)++result) { | ||
| 377 | *result = *first; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | template <ranges::input_range R, typename OutputIterator> | ||
| 382 | constexpr void operator()(R&& r, OutputIterator result) const { | ||
| 383 | return operator()(ranges::begin(r), ranges::end(r), std::move(result)); | ||
| 384 | } | ||
| 385 | }; | ||
| 386 | |||
| 387 | struct copy_if_fn { | ||
| 388 | template <typename InputIterator, typename OutputIterator, typename Proj = std::identity, | ||
| 389 | typename Pred> | ||
| 390 | constexpr void operator()(InputIterator first, InputIterator last, OutputIterator result, | ||
| 391 | Pred pred, Proj proj = {}) const { | ||
| 392 | for (; first != last; ++first) { | ||
| 393 | if (std::invoke(pred, std::invoke(proj, *first))) { | ||
| 394 | *result = *first; | ||
| 395 | ++result; | ||
| 396 | } | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | template <ranges::input_range R, typename OutputIterator, typename Proj = std::identity, | ||
| 401 | typename Pred> | ||
| 402 | constexpr void operator()(R&& r, OutputIterator result, Pred pred, Proj proj = {}) const { | ||
| 403 | return operator()(ranges::begin(r), ranges::end(r), std::move(result), std::ref(pred), | ||
| 404 | std::ref(proj)); | ||
| 405 | } | ||
| 406 | }; | ||
| 407 | |||
| 408 | inline constexpr copy_fn copy; | ||
| 409 | inline constexpr copy_if_fn copy_if; | ||
| 410 | |||
| 411 | // | ||
| 412 | // generate | ||
| 413 | // | ||
| 414 | |||
| 415 | struct generate_fn { | ||
| 416 | template <typename Iterator, typename F> | ||
| 417 | constexpr Iterator operator()(Iterator first, Iterator last, F gen) const { | ||
| 418 | for (; first != last; *first = std::invoke(gen), ++first) | ||
| 419 | ; | ||
| 420 | return first; | ||
| 421 | } | ||
| 422 | |||
| 423 | template <typename R, std::copy_constructible F> | ||
| 424 | requires std::invocable<F&> && ranges::output_range<R> | ||
| 425 | constexpr ranges::iterator_t<R> operator()(R&& r, F gen) const { | ||
| 426 | return operator()(ranges::begin(r), ranges::end(r), std::move(gen)); | ||
| 427 | } | ||
| 428 | }; | ||
| 429 | |||
| 430 | inline constexpr generate_fn generate; | ||
| 431 | |||
| 432 | // | ||
| 433 | // lower_bound, upper_bound | ||
| 434 | // | ||
| 435 | |||
| 436 | struct lower_bound_fn { | ||
| 437 | template <typename Iterator, typename T, typename Proj = std::identity, | ||
| 438 | typename Comp = ranges::less> | ||
| 439 | constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {}, | ||
| 440 | Proj proj = {}) const { | ||
| 441 | Iterator it; | ||
| 442 | std::ptrdiff_t _count, _step; | ||
| 443 | _count = std::distance(first, last); | ||
| 444 | |||
| 445 | while (_count > 0) { | ||
| 446 | it = first; | ||
| 447 | _step = _count / 2; | ||
| 448 | ranges::advance(it, _step, last); | ||
| 449 | if (comp(std::invoke(proj, *it), value)) { | ||
| 450 | first = ++it; | ||
| 451 | _count -= _step + 1; | ||
| 452 | } else { | ||
| 453 | _count = _step; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | return first; | ||
| 457 | } | ||
| 458 | |||
| 459 | template <ranges::input_range R, typename T, typename Proj = std::identity, | ||
| 460 | typename Comp = ranges::less> | ||
| 461 | constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {}, | ||
| 462 | Proj proj = {}) const { | ||
| 463 | return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj)); | ||
| 464 | } | ||
| 465 | }; | ||
| 466 | |||
| 467 | struct upper_bound_fn { | ||
| 468 | template <typename Iterator, typename T, typename Proj = std::identity, | ||
| 469 | typename Comp = ranges::less> | ||
| 470 | constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {}, | ||
| 471 | Proj proj = {}) const { | ||
| 472 | Iterator it; | ||
| 473 | std::ptrdiff_t _count, _step; | ||
| 474 | _count = std::distance(first, last); | ||
| 475 | |||
| 476 | while (_count > 0) { | ||
| 477 | it = first; | ||
| 478 | _step = _count / 2; | ||
| 479 | ranges::advance(it, _step, last); | ||
| 480 | if (!comp(value, std::invoke(proj, *it))) { | ||
| 481 | first = ++it; | ||
| 482 | _count -= _step + 1; | ||
| 483 | } else { | ||
| 484 | _count = _step; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | return first; | ||
| 488 | } | ||
| 489 | |||
| 490 | template <ranges::input_range R, typename T, typename Proj = std::identity, | ||
| 491 | typename Comp = ranges::less> | ||
| 492 | constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {}, | ||
| 493 | Proj proj = {}) const { | ||
| 494 | return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj)); | ||
| 495 | } | ||
| 496 | }; | ||
| 497 | |||
| 498 | inline constexpr lower_bound_fn lower_bound; | ||
| 499 | inline constexpr upper_bound_fn upper_bound; | ||
| 500 | |||
| 501 | // | ||
| 502 | // adjacent_find | ||
| 503 | // | ||
| 504 | |||
| 505 | struct adjacent_find_fn { | ||
| 506 | template <typename Iterator, typename Proj = std::identity, typename Pred = ranges::equal_to> | ||
| 507 | constexpr Iterator operator()(Iterator first, Iterator last, Pred pred = {}, | ||
| 508 | Proj proj = {}) const { | ||
| 509 | if (first == last) | ||
| 510 | return first; | ||
| 511 | auto _next = ranges::next(first); | ||
| 512 | for (; _next != last; ++_next, ++first) | ||
| 513 | if (std::invoke(pred, std::invoke(proj, *first), std::invoke(proj, *_next))) | ||
| 514 | return first; | ||
| 515 | return _next; | ||
| 516 | } | ||
| 517 | |||
| 518 | template <ranges::input_range R, typename Proj = std::identity, | ||
| 519 | typename Pred = ranges::equal_to> | ||
| 520 | constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred = {}, Proj proj = {}) const { | ||
| 521 | return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj)); | ||
| 522 | } | ||
| 523 | }; | ||
| 524 | |||
| 525 | inline constexpr adjacent_find_fn adjacent_find; | ||
| 526 | |||
| 527 | } // namespace ranges | ||
| 528 | } // namespace std | ||
| 529 | |||
| 530 | #endif | ||
diff --git a/src/common/polyfill_thread.h b/src/common/polyfill_thread.h new file mode 100644 index 000000000..5a8d1ce08 --- /dev/null +++ b/src/common/polyfill_thread.h | |||
| @@ -0,0 +1,323 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | // | ||
| 5 | // TODO: remove this file when jthread is supported by all compilation targets | ||
| 6 | // | ||
| 7 | |||
| 8 | #pragma once | ||
| 9 | |||
| 10 | #include <version> | ||
| 11 | |||
| 12 | #ifdef __cpp_lib_jthread | ||
| 13 | |||
| 14 | #include <stop_token> | ||
| 15 | #include <thread> | ||
| 16 | |||
| 17 | namespace Common { | ||
| 18 | |||
| 19 | template <typename Condvar, typename Lock, typename Pred> | ||
| 20 | void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) { | ||
| 21 | cv.wait(lock, token, std::move(pred)); | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace Common | ||
| 25 | |||
| 26 | #else | ||
| 27 | |||
| 28 | #include <atomic> | ||
| 29 | #include <functional> | ||
| 30 | #include <list> | ||
| 31 | #include <memory> | ||
| 32 | #include <mutex> | ||
| 33 | #include <optional> | ||
| 34 | #include <thread> | ||
| 35 | #include <type_traits> | ||
| 36 | |||
| 37 | namespace std { | ||
| 38 | namespace polyfill { | ||
| 39 | |||
| 40 | using stop_state_callbacks = list<function<void()>>; | ||
| 41 | |||
| 42 | class stop_state { | ||
| 43 | public: | ||
| 44 | stop_state() = default; | ||
| 45 | ~stop_state() = default; | ||
| 46 | |||
| 47 | bool request_stop() { | ||
| 48 | stop_state_callbacks callbacks; | ||
| 49 | |||
| 50 | { | ||
| 51 | scoped_lock lk{m_lock}; | ||
| 52 | |||
| 53 | if (m_stop_requested.load()) { | ||
| 54 | // Already set, nothing to do | ||
| 55 | return false; | ||
| 56 | } | ||
| 57 | |||
| 58 | // Set as requested | ||
| 59 | m_stop_requested = true; | ||
| 60 | |||
| 61 | // Copy callback list | ||
| 62 | callbacks = m_callbacks; | ||
| 63 | } | ||
| 64 | |||
| 65 | for (auto callback : callbacks) { | ||
| 66 | callback(); | ||
| 67 | } | ||
| 68 | |||
| 69 | return true; | ||
| 70 | } | ||
| 71 | |||
| 72 | bool stop_requested() const { | ||
| 73 | return m_stop_requested.load(); | ||
| 74 | } | ||
| 75 | |||
| 76 | stop_state_callbacks::const_iterator insert_callback(function<void()> f) { | ||
| 77 | stop_state_callbacks::const_iterator ret{}; | ||
| 78 | bool should_run{}; | ||
| 79 | |||
| 80 | { | ||
| 81 | scoped_lock lk{m_lock}; | ||
| 82 | should_run = m_stop_requested.load(); | ||
| 83 | m_callbacks.push_front(f); | ||
| 84 | ret = m_callbacks.begin(); | ||
| 85 | } | ||
| 86 | |||
| 87 | if (should_run) { | ||
| 88 | f(); | ||
| 89 | } | ||
| 90 | |||
| 91 | return ret; | ||
| 92 | } | ||
| 93 | |||
| 94 | void remove_callback(stop_state_callbacks::const_iterator it) { | ||
| 95 | scoped_lock lk{m_lock}; | ||
| 96 | m_callbacks.erase(it); | ||
| 97 | } | ||
| 98 | |||
| 99 | private: | ||
| 100 | mutex m_lock; | ||
| 101 | atomic<bool> m_stop_requested; | ||
| 102 | stop_state_callbacks m_callbacks; | ||
| 103 | }; | ||
| 104 | |||
| 105 | } // namespace polyfill | ||
| 106 | |||
| 107 | class stop_token; | ||
| 108 | class stop_source; | ||
| 109 | struct nostopstate_t { | ||
| 110 | explicit nostopstate_t() = default; | ||
| 111 | }; | ||
| 112 | inline constexpr nostopstate_t nostopstate{}; | ||
| 113 | |||
| 114 | template <class Callback> | ||
| 115 | class stop_callback; | ||
| 116 | |||
| 117 | class stop_token { | ||
| 118 | public: | ||
| 119 | stop_token() noexcept = default; | ||
| 120 | |||
| 121 | stop_token(const stop_token&) noexcept = default; | ||
| 122 | stop_token(stop_token&&) noexcept = default; | ||
| 123 | stop_token& operator=(const stop_token&) noexcept = default; | ||
| 124 | stop_token& operator=(stop_token&&) noexcept = default; | ||
| 125 | ~stop_token() = default; | ||
| 126 | |||
| 127 | void swap(stop_token& other) noexcept { | ||
| 128 | m_stop_state.swap(other.m_stop_state); | ||
| 129 | } | ||
| 130 | |||
| 131 | [[nodiscard]] bool stop_requested() const noexcept { | ||
| 132 | return m_stop_state && m_stop_state->stop_requested(); | ||
| 133 | } | ||
| 134 | [[nodiscard]] bool stop_possible() const noexcept { | ||
| 135 | return m_stop_state != nullptr; | ||
| 136 | } | ||
| 137 | |||
| 138 | private: | ||
| 139 | friend class stop_source; | ||
| 140 | template <typename Callback> | ||
| 141 | friend class stop_callback; | ||
| 142 | stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(move(stop_state)) {} | ||
| 143 | |||
| 144 | private: | ||
| 145 | shared_ptr<polyfill::stop_state> m_stop_state; | ||
| 146 | }; | ||
| 147 | |||
| 148 | class stop_source { | ||
| 149 | public: | ||
| 150 | stop_source() : m_stop_state(make_shared<polyfill::stop_state>()) {} | ||
| 151 | explicit stop_source(nostopstate_t) noexcept {} | ||
| 152 | |||
| 153 | stop_source(const stop_source&) noexcept = default; | ||
| 154 | stop_source(stop_source&&) noexcept = default; | ||
| 155 | stop_source& operator=(const stop_source&) noexcept = default; | ||
| 156 | stop_source& operator=(stop_source&&) noexcept = default; | ||
| 157 | ~stop_source() = default; | ||
| 158 | void swap(stop_source& other) noexcept { | ||
| 159 | m_stop_state.swap(other.m_stop_state); | ||
| 160 | } | ||
| 161 | |||
| 162 | [[nodiscard]] stop_token get_token() const noexcept { | ||
| 163 | return stop_token(m_stop_state); | ||
| 164 | } | ||
| 165 | [[nodiscard]] bool stop_possible() const noexcept { | ||
| 166 | return m_stop_state != nullptr; | ||
| 167 | } | ||
| 168 | [[nodiscard]] bool stop_requested() const noexcept { | ||
| 169 | return m_stop_state && m_stop_state->stop_requested(); | ||
| 170 | } | ||
| 171 | bool request_stop() noexcept { | ||
| 172 | return m_stop_state && m_stop_state->request_stop(); | ||
| 173 | } | ||
| 174 | |||
| 175 | private: | ||
| 176 | friend class jthread; | ||
| 177 | explicit stop_source(shared_ptr<polyfill::stop_state> stop_state) | ||
| 178 | : m_stop_state(move(stop_state)) {} | ||
| 179 | |||
| 180 | private: | ||
| 181 | shared_ptr<polyfill::stop_state> m_stop_state; | ||
| 182 | }; | ||
| 183 | |||
| 184 | template <typename Callback> | ||
| 185 | class stop_callback { | ||
| 186 | static_assert(is_nothrow_destructible_v<Callback>); | ||
| 187 | static_assert(is_invocable_v<Callback>); | ||
| 188 | |||
| 189 | public: | ||
| 190 | using callback_type = Callback; | ||
| 191 | |||
| 192 | template <typename C> | ||
| 193 | requires constructible_from<Callback, C> | ||
| 194 | explicit stop_callback(const stop_token& st, | ||
| 195 | C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) | ||
| 196 | : m_stop_state(st.m_stop_state) { | ||
| 197 | if (m_stop_state) { | ||
| 198 | m_callback = m_stop_state->insert_callback(move(cb)); | ||
| 199 | } | ||
| 200 | } | ||
| 201 | template <typename C> | ||
| 202 | requires constructible_from<Callback, C> | ||
| 203 | explicit stop_callback(stop_token&& st, | ||
| 204 | C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>) | ||
| 205 | : m_stop_state(move(st.m_stop_state)) { | ||
| 206 | if (m_stop_state) { | ||
| 207 | m_callback = m_stop_state->insert_callback(move(cb)); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | ~stop_callback() { | ||
| 211 | if (m_stop_state && m_callback) { | ||
| 212 | m_stop_state->remove_callback(*m_callback); | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | stop_callback(const stop_callback&) = delete; | ||
| 217 | stop_callback(stop_callback&&) = delete; | ||
| 218 | stop_callback& operator=(const stop_callback&) = delete; | ||
| 219 | stop_callback& operator=(stop_callback&&) = delete; | ||
| 220 | |||
| 221 | private: | ||
| 222 | shared_ptr<polyfill::stop_state> m_stop_state; | ||
| 223 | optional<polyfill::stop_state_callbacks::const_iterator> m_callback; | ||
| 224 | }; | ||
| 225 | |||
| 226 | template <typename Callback> | ||
| 227 | stop_callback(stop_token, Callback) -> stop_callback<Callback>; | ||
| 228 | |||
| 229 | class jthread { | ||
| 230 | public: | ||
| 231 | using id = thread::id; | ||
| 232 | using native_handle_type = thread::native_handle_type; | ||
| 233 | |||
| 234 | jthread() noexcept = default; | ||
| 235 | |||
| 236 | template <typename F, typename... Args, | ||
| 237 | typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>> | ||
| 238 | explicit jthread(F&& f, Args&&... args) | ||
| 239 | : m_stop_state(make_shared<polyfill::stop_state>()), | ||
| 240 | m_thread(make_thread(move(f), move(args)...)) {} | ||
| 241 | |||
| 242 | ~jthread() { | ||
| 243 | if (joinable()) { | ||
| 244 | request_stop(); | ||
| 245 | join(); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | jthread(const jthread&) = delete; | ||
| 250 | jthread(jthread&&) noexcept = default; | ||
| 251 | jthread& operator=(const jthread&) = delete; | ||
| 252 | |||
| 253 | jthread& operator=(jthread&& other) noexcept { | ||
| 254 | m_thread.swap(other.m_thread); | ||
| 255 | m_stop_state.swap(other.m_stop_state); | ||
| 256 | return *this; | ||
| 257 | } | ||
| 258 | |||
| 259 | void swap(jthread& other) noexcept { | ||
| 260 | m_thread.swap(other.m_thread); | ||
| 261 | m_stop_state.swap(other.m_stop_state); | ||
| 262 | } | ||
| 263 | [[nodiscard]] bool joinable() const noexcept { | ||
| 264 | return m_thread.joinable(); | ||
| 265 | } | ||
| 266 | void join() { | ||
| 267 | m_thread.join(); | ||
| 268 | } | ||
| 269 | void detach() { | ||
| 270 | m_thread.detach(); | ||
| 271 | m_stop_state.reset(); | ||
| 272 | } | ||
| 273 | |||
| 274 | [[nodiscard]] id get_id() const noexcept { | ||
| 275 | return m_thread.get_id(); | ||
| 276 | } | ||
| 277 | [[nodiscard]] native_handle_type native_handle() { | ||
| 278 | return m_thread.native_handle(); | ||
| 279 | } | ||
| 280 | [[nodiscard]] stop_source get_stop_source() noexcept { | ||
| 281 | return stop_source(m_stop_state); | ||
| 282 | } | ||
| 283 | [[nodiscard]] stop_token get_stop_token() const noexcept { | ||
| 284 | return stop_source(m_stop_state).get_token(); | ||
| 285 | } | ||
| 286 | bool request_stop() noexcept { | ||
| 287 | return get_stop_source().request_stop(); | ||
| 288 | } | ||
| 289 | [[nodiscard]] static unsigned int hardware_concurrency() noexcept { | ||
| 290 | return thread::hardware_concurrency(); | ||
| 291 | } | ||
| 292 | |||
| 293 | private: | ||
| 294 | template <typename F, typename... Args> | ||
| 295 | thread make_thread(F&& f, Args&&... args) { | ||
| 296 | if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) { | ||
| 297 | return thread(move(f), get_stop_token(), move(args)...); | ||
| 298 | } else { | ||
| 299 | return thread(move(f), move(args)...); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | shared_ptr<polyfill::stop_state> m_stop_state; | ||
| 304 | thread m_thread; | ||
| 305 | }; | ||
| 306 | |||
| 307 | } // namespace std | ||
| 308 | |||
| 309 | namespace Common { | ||
| 310 | |||
| 311 | template <typename Condvar, typename Lock, typename Pred> | ||
| 312 | void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) { | ||
| 313 | if (token.stop_requested()) { | ||
| 314 | return; | ||
| 315 | } | ||
| 316 | |||
| 317 | std::stop_callback callback(token, [&] { cv.notify_all(); }); | ||
| 318 | cv.wait(lock, [&] { return pred() || token.stop_requested(); }); | ||
| 319 | } | ||
| 320 | |||
| 321 | } // namespace Common | ||
| 322 | |||
| 323 | #endif | ||
diff --git a/src/common/precompiled_headers.h b/src/common/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/common/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/common/settings.h b/src/common/settings.h index 00e4421f7..29b730cff 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -19,6 +19,7 @@ namespace Settings { | |||
| 19 | enum class RendererBackend : u32 { | 19 | enum class RendererBackend : u32 { |
| 20 | OpenGL = 0, | 20 | OpenGL = 0, |
| 21 | Vulkan = 1, | 21 | Vulkan = 1, |
| 22 | Null = 2, | ||
| 22 | }; | 23 | }; |
| 23 | 24 | ||
| 24 | enum class ShaderBackend : u32 { | 25 | enum class ShaderBackend : u32 { |
| @@ -399,6 +400,7 @@ struct Values { | |||
| 399 | Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; | 400 | Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; |
| 400 | Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; | 401 | Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"}; |
| 401 | Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; | 402 | Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"}; |
| 403 | Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"}; | ||
| 402 | 404 | ||
| 403 | SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; | 405 | SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; |
| 404 | SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; | 406 | SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; |
| @@ -411,7 +413,7 @@ struct Values { | |||
| 411 | 413 | ||
| 412 | // Renderer | 414 | // Renderer |
| 413 | SwitchableSetting<RendererBackend, true> renderer_backend{ | 415 | SwitchableSetting<RendererBackend, true> renderer_backend{ |
| 414 | RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"}; | 416 | RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"}; |
| 415 | Setting<bool> renderer_debug{false, "debug"}; | 417 | Setting<bool> renderer_debug{false, "debug"}; |
| 416 | Setting<bool> renderer_shader_feedback{false, "shader_feedback"}; | 418 | Setting<bool> renderer_shader_feedback{false, "shader_feedback"}; |
| 417 | Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; | 419 | Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"}; |
diff --git a/src/common/settings_input.h b/src/common/settings_input.h index 485e4ad22..46f38c703 100644 --- a/src/common/settings_input.h +++ b/src/common/settings_input.h | |||
| @@ -391,6 +391,7 @@ struct PlayerInput { | |||
| 391 | u32 body_color_right; | 391 | u32 body_color_right; |
| 392 | u32 button_color_left; | 392 | u32 button_color_left; |
| 393 | u32 button_color_right; | 393 | u32 button_color_right; |
| 394 | std::string profile_name; | ||
| 394 | }; | 395 | }; |
| 395 | 396 | ||
| 396 | struct TouchscreenInput { | 397 | struct TouchscreenInput { |
diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 7a495bc79..b26db4796 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp | |||
| @@ -141,7 +141,7 @@ static std::wstring CPToUTF16(u32 code_page, const std::string& input) { | |||
| 141 | MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0); | 141 | MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0); |
| 142 | 142 | ||
| 143 | if (size == 0) { | 143 | if (size == 0) { |
| 144 | return L""; | 144 | return {}; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | std::wstring output(size, L'\0'); | 147 | std::wstring output(size, L'\0'); |
| @@ -158,7 +158,7 @@ std::string UTF16ToUTF8(const std::wstring& input) { | |||
| 158 | const auto size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), | 158 | const auto size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()), |
| 159 | nullptr, 0, nullptr, nullptr); | 159 | nullptr, 0, nullptr, nullptr); |
| 160 | if (size == 0) { | 160 | if (size == 0) { |
| 161 | return ""; | 161 | return {}; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | std::string output(size, '\0'); | 164 | std::string output(size, '\0'); |
diff --git a/src/common/thread_worker.h b/src/common/thread_worker.h index 62c60f724..260ad44e4 100644 --- a/src/common/thread_worker.h +++ b/src/common/thread_worker.h | |||
| @@ -7,13 +7,13 @@ | |||
| 7 | #include <condition_variable> | 7 | #include <condition_variable> |
| 8 | #include <functional> | 8 | #include <functional> |
| 9 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <stop_token> | ||
| 11 | #include <string> | 10 | #include <string> |
| 12 | #include <thread> | 11 | #include <thread> |
| 13 | #include <type_traits> | 12 | #include <type_traits> |
| 14 | #include <vector> | 13 | #include <vector> |
| 15 | #include <queue> | 14 | #include <queue> |
| 16 | 15 | ||
| 16 | #include "common/polyfill_thread.h" | ||
| 17 | #include "common/thread.h" | 17 | #include "common/thread.h" |
| 18 | #include "common/unique_function.h" | 18 | #include "common/unique_function.h" |
| 19 | 19 | ||
| @@ -47,7 +47,8 @@ public: | |||
| 47 | if (requests.empty()) { | 47 | if (requests.empty()) { |
| 48 | wait_condition.notify_all(); | 48 | wait_condition.notify_all(); |
| 49 | } | 49 | } |
| 50 | condition.wait(lock, stop_token, [this] { return !requests.empty(); }); | 50 | Common::CondvarWait(condition, lock, stop_token, |
| 51 | [this] { return !requests.empty(); }); | ||
| 51 | if (stop_token.stop_requested()) { | 52 | if (stop_token.stop_requested()) { |
| 52 | break; | 53 | break; |
| 53 | } | 54 | } |
diff --git a/src/common/threadsafe_queue.h b/src/common/threadsafe_queue.h index 053798e79..2ef1da064 100644 --- a/src/common/threadsafe_queue.h +++ b/src/common/threadsafe_queue.h | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | #include <mutex> | 12 | #include <mutex> |
| 13 | #include <utility> | 13 | #include <utility> |
| 14 | 14 | ||
| 15 | #include "common/polyfill_thread.h" | ||
| 16 | |||
| 15 | namespace Common { | 17 | namespace Common { |
| 16 | template <typename T, bool with_stop_token = false> | 18 | template <typename T, bool with_stop_token = false> |
| 17 | class SPSCQueue { | 19 | class SPSCQueue { |
| @@ -97,7 +99,7 @@ public: | |||
| 97 | T PopWait(std::stop_token stop_token) { | 99 | T PopWait(std::stop_token stop_token) { |
| 98 | if (Empty()) { | 100 | if (Empty()) { |
| 99 | std::unique_lock lock{cv_mutex}; | 101 | std::unique_lock lock{cv_mutex}; |
| 100 | cv.wait(lock, stop_token, [this] { return !Empty(); }); | 102 | Common::CondvarWait(cv, lock, stop_token, [this] { return !Empty(); }); |
| 101 | } | 103 | } |
| 102 | if (stop_token.stop_requested()) { | 104 | if (stop_token.stop_requested()) { |
| 103 | return T{}; | 105 | return T{}; |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 5629980d9..c6b5ac196 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -528,6 +528,8 @@ add_library(core STATIC | |||
| 528 | hle/service/mnpp/mnpp_app.h | 528 | hle/service/mnpp/mnpp_app.h |
| 529 | hle/service/ncm/ncm.cpp | 529 | hle/service/ncm/ncm.cpp |
| 530 | hle/service/ncm/ncm.h | 530 | hle/service/ncm/ncm.h |
| 531 | hle/service/nfc/mifare_user.cpp | ||
| 532 | hle/service/nfc/mifare_user.h | ||
| 531 | hle/service/nfc/nfc.cpp | 533 | hle/service/nfc/nfc.cpp |
| 532 | hle/service/nfc/nfc.h | 534 | hle/service/nfc/nfc.h |
| 533 | hle/service/nfc/nfc_device.cpp | 535 | hle/service/nfc/nfc_device.cpp |
| @@ -771,6 +773,7 @@ add_library(core STATIC | |||
| 771 | memory.h | 773 | memory.h |
| 772 | perf_stats.cpp | 774 | perf_stats.cpp |
| 773 | perf_stats.h | 775 | perf_stats.h |
| 776 | precompiled_headers.h | ||
| 774 | reporter.cpp | 777 | reporter.cpp |
| 775 | reporter.h | 778 | reporter.h |
| 776 | telemetry_session.cpp | 779 | telemetry_session.cpp |
| @@ -823,5 +826,9 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) | |||
| 823 | hle/service/jit/jit.cpp | 826 | hle/service/jit/jit.cpp |
| 824 | hle/service/jit/jit.h | 827 | hle/service/jit/jit.h |
| 825 | ) | 828 | ) |
| 826 | target_link_libraries(core PRIVATE dynarmic) | 829 | target_link_libraries(core PRIVATE dynarmic::dynarmic) |
| 830 | endif() | ||
| 831 | |||
| 832 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 833 | target_precompile_headers(core PRIVATE precompiled_headers.h) | ||
| 827 | endif() | 834 | endif() |
diff --git a/src/core/arm/arm_interface.cpp b/src/core/arm/arm_interface.cpp index 29ba562dc..2df7b0ee8 100644 --- a/src/core/arm/arm_interface.cpp +++ b/src/core/arm/arm_interface.cpp | |||
| @@ -145,11 +145,15 @@ void ARM_Interface::Run() { | |||
| 145 | // Notify the debugger and go to sleep if a breakpoint was hit, | 145 | // Notify the debugger and go to sleep if a breakpoint was hit, |
| 146 | // or if the thread is unable to continue for any reason. | 146 | // or if the thread is unable to continue for any reason. |
| 147 | if (Has(hr, breakpoint) || Has(hr, no_execute)) { | 147 | if (Has(hr, breakpoint) || Has(hr, no_execute)) { |
| 148 | RewindBreakpointInstruction(); | 148 | if (!Has(hr, no_execute)) { |
| 149 | RewindBreakpointInstruction(); | ||
| 150 | } | ||
| 149 | if (system.DebuggerEnabled()) { | 151 | if (system.DebuggerEnabled()) { |
| 150 | system.GetDebugger().NotifyThreadStopped(current_thread); | 152 | system.GetDebugger().NotifyThreadStopped(current_thread); |
| 153 | } else { | ||
| 154 | LogBacktrace(); | ||
| 151 | } | 155 | } |
| 152 | current_thread->RequestSuspend(Kernel::SuspendType::Debug); | 156 | current_thread->RequestSuspend(SuspendType::Debug); |
| 153 | break; | 157 | break; |
| 154 | } | 158 | } |
| 155 | 159 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 227e06ea1..947747d36 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -29,7 +29,9 @@ class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { | |||
| 29 | public: | 29 | public: |
| 30 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) | 30 | explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) |
| 31 | : parent{parent_}, | 31 | : parent{parent_}, |
| 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} | 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, |
| 33 | check_memory_access{debugger_enabled || | ||
| 34 | !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} | ||
| 33 | 35 | ||
| 34 | u8 MemoryRead8(u32 vaddr) override { | 36 | u8 MemoryRead8(u32 vaddr) override { |
| 35 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); | 37 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); |
| @@ -154,6 +156,17 @@ public: | |||
| 154 | } | 156 | } |
| 155 | 157 | ||
| 156 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { | 158 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { |
| 159 | if (!check_memory_access) { | ||
| 160 | return true; | ||
| 161 | } | ||
| 162 | |||
| 163 | if (!memory.IsValidVirtualAddressRange(addr, size)) { | ||
| 164 | LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", | ||
| 165 | addr); | ||
| 166 | parent.jit.load()->HaltExecution(ARM_Interface::no_execute); | ||
| 167 | return false; | ||
| 168 | } | ||
| 169 | |||
| 157 | if (!debugger_enabled) { | 170 | if (!debugger_enabled) { |
| 158 | return true; | 171 | return true; |
| 159 | } | 172 | } |
| @@ -181,7 +194,8 @@ public: | |||
| 181 | ARM_Dynarmic_32& parent; | 194 | ARM_Dynarmic_32& parent; |
| 182 | Core::Memory::Memory& memory; | 195 | Core::Memory::Memory& memory; |
| 183 | std::size_t num_interpreted_instructions{}; | 196 | std::size_t num_interpreted_instructions{}; |
| 184 | bool debugger_enabled{}; | 197 | const bool debugger_enabled{}; |
| 198 | const bool check_memory_access{}; | ||
| 185 | static constexpr u64 minimum_run_cycles = 10000U; | 199 | static constexpr u64 minimum_run_cycles = 10000U; |
| 186 | }; | 200 | }; |
| 187 | 201 | ||
| @@ -264,6 +278,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 264 | if (!Settings::values.cpuopt_recompile_exclusives) { | 278 | if (!Settings::values.cpuopt_recompile_exclusives) { |
| 265 | config.recompile_on_exclusive_fastmem_failure = false; | 279 | config.recompile_on_exclusive_fastmem_failure = false; |
| 266 | } | 280 | } |
| 281 | if (!Settings::values.cpuopt_ignore_memory_aborts) { | ||
| 282 | config.check_halt_on_memory_access = true; | ||
| 283 | } | ||
| 267 | } else { | 284 | } else { |
| 268 | // Unsafe optimizations | 285 | // Unsafe optimizations |
| 269 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 286 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index cb53d64ba..3df943df7 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -29,7 +29,9 @@ class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { | |||
| 29 | public: | 29 | public: |
| 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) | 30 | explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) |
| 31 | : parent{parent_}, | 31 | : parent{parent_}, |
| 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {} | 32 | memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()}, |
| 33 | check_memory_access{debugger_enabled || | ||
| 34 | !Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {} | ||
| 33 | 35 | ||
| 34 | u8 MemoryRead8(u64 vaddr) override { | 36 | u8 MemoryRead8(u64 vaddr) override { |
| 35 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); | 37 | CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read); |
| @@ -198,6 +200,17 @@ public: | |||
| 198 | } | 200 | } |
| 199 | 201 | ||
| 200 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { | 202 | bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) { |
| 203 | if (!check_memory_access) { | ||
| 204 | return true; | ||
| 205 | } | ||
| 206 | |||
| 207 | if (!memory.IsValidVirtualAddressRange(addr, size)) { | ||
| 208 | LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", | ||
| 209 | addr); | ||
| 210 | parent.jit.load()->HaltExecution(ARM_Interface::no_execute); | ||
| 211 | return false; | ||
| 212 | } | ||
| 213 | |||
| 201 | if (!debugger_enabled) { | 214 | if (!debugger_enabled) { |
| 202 | return true; | 215 | return true; |
| 203 | } | 216 | } |
| @@ -226,7 +239,8 @@ public: | |||
| 226 | Core::Memory::Memory& memory; | 239 | Core::Memory::Memory& memory; |
| 227 | u64 tpidrro_el0 = 0; | 240 | u64 tpidrro_el0 = 0; |
| 228 | u64 tpidr_el0 = 0; | 241 | u64 tpidr_el0 = 0; |
| 229 | bool debugger_enabled{}; | 242 | const bool debugger_enabled{}; |
| 243 | const bool check_memory_access{}; | ||
| 230 | static constexpr u64 minimum_run_cycles = 10000U; | 244 | static constexpr u64 minimum_run_cycles = 10000U; |
| 231 | }; | 245 | }; |
| 232 | 246 | ||
| @@ -323,6 +337,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 323 | if (!Settings::values.cpuopt_recompile_exclusives) { | 337 | if (!Settings::values.cpuopt_recompile_exclusives) { |
| 324 | config.recompile_on_exclusive_fastmem_failure = false; | 338 | config.recompile_on_exclusive_fastmem_failure = false; |
| 325 | } | 339 | } |
| 340 | if (!Settings::values.cpuopt_ignore_memory_aborts) { | ||
| 341 | config.check_halt_on_memory_access = true; | ||
| 342 | } | ||
| 326 | } else { | 343 | } else { |
| 327 | // Unsafe optimizations | 344 | // Unsafe optimizations |
| 328 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 345 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 95ea3ef39..374367468 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <thread> | 10 | #include <thread> |
| 11 | 11 | ||
| 12 | #include "common/fiber.h" | 12 | #include "common/fiber.h" |
| 13 | #include "common/polyfill_thread.h" | ||
| 13 | #include "common/thread.h" | 14 | #include "common/thread.h" |
| 14 | #include "core/hardware_properties.h" | 15 | #include "core/hardware_properties.h" |
| 15 | 16 | ||
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp index 1a8e02e6a..a9675df76 100644 --- a/src/core/debugger/debugger.cpp +++ b/src/core/debugger/debugger.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <boost/process/async_pipe.hpp> | 9 | #include <boost/process/async_pipe.hpp> |
| 10 | 10 | ||
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/polyfill_thread.h" | ||
| 12 | #include "common/thread.h" | 13 | #include "common/thread.h" |
| 13 | #include "core/core.h" | 14 | #include "core/core.h" |
| 14 | #include "core/debugger/debugger.h" | 15 | #include "core/debugger/debugger.h" |
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp index 78e56bbbd..50303fe42 100644 --- a/src/core/file_sys/content_archive.cpp +++ b/src/core/file_sys/content_archive.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <utility> | 7 | #include <utility> |
| 8 | 8 | ||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "core/crypto/aes_util.h" | 11 | #include "core/crypto/aes_util.h" |
| 11 | #include "core/crypto/ctr_encryption_layer.h" | 12 | #include "core/crypto/ctr_encryption_layer.h" |
| 12 | #include "core/crypto/key_manager.h" | 13 | #include "core/crypto/key_manager.h" |
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp index 6c230f619..52919484e 100644 --- a/src/core/frontend/applets/controller.cpp +++ b/src/core/frontend/applets/controller.cpp | |||
| @@ -16,7 +16,7 @@ DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) : hid_ | |||
| 16 | 16 | ||
| 17 | DefaultControllerApplet::~DefaultControllerApplet() = default; | 17 | DefaultControllerApplet::~DefaultControllerApplet() = default; |
| 18 | 18 | ||
| 19 | void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback, | 19 | void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callback, |
| 20 | const ControllerParameters& parameters) const { | 20 | const ControllerParameters& parameters) const { |
| 21 | LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); | 21 | LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!"); |
| 22 | 22 | ||
diff --git a/src/core/frontend/applets/controller.h b/src/core/frontend/applets/controller.h index 1d2850ad5..adb2feefd 100644 --- a/src/core/frontend/applets/controller.h +++ b/src/core/frontend/applets/controller.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | #include <vector> | ||
| 7 | 8 | ||
| 8 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 9 | 10 | ||
| @@ -35,9 +36,11 @@ struct ControllerParameters { | |||
| 35 | 36 | ||
| 36 | class ControllerApplet { | 37 | class ControllerApplet { |
| 37 | public: | 38 | public: |
| 39 | using ReconfigureCallback = std::function<void()>; | ||
| 40 | |||
| 38 | virtual ~ControllerApplet(); | 41 | virtual ~ControllerApplet(); |
| 39 | 42 | ||
| 40 | virtual void ReconfigureControllers(std::function<void()> callback, | 43 | virtual void ReconfigureControllers(ReconfigureCallback callback, |
| 41 | const ControllerParameters& parameters) const = 0; | 44 | const ControllerParameters& parameters) const = 0; |
| 42 | }; | 45 | }; |
| 43 | 46 | ||
| @@ -46,7 +49,7 @@ public: | |||
| 46 | explicit DefaultControllerApplet(HID::HIDCore& hid_core_); | 49 | explicit DefaultControllerApplet(HID::HIDCore& hid_core_); |
| 47 | ~DefaultControllerApplet() override; | 50 | ~DefaultControllerApplet() override; |
| 48 | 51 | ||
| 49 | void ReconfigureControllers(std::function<void()> callback, | 52 | void ReconfigureControllers(ReconfigureCallback callback, |
| 50 | const ControllerParameters& parameters) const override; | 53 | const ControllerParameters& parameters) const override; |
| 51 | 54 | ||
| 52 | private: | 55 | private: |
diff --git a/src/core/frontend/applets/error.cpp b/src/core/frontend/applets/error.cpp index f8b961098..69c2b2b4d 100644 --- a/src/core/frontend/applets/error.cpp +++ b/src/core/frontend/applets/error.cpp | |||
| @@ -8,13 +8,13 @@ namespace Core::Frontend { | |||
| 8 | 8 | ||
| 9 | ErrorApplet::~ErrorApplet() = default; | 9 | ErrorApplet::~ErrorApplet() = default; |
| 10 | 10 | ||
| 11 | void DefaultErrorApplet::ShowError(Result error, std::function<void()> finished) const { | 11 | void DefaultErrorApplet::ShowError(Result error, FinishedCallback finished) const { |
| 12 | LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})", | 12 | LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})", |
| 13 | error.module.Value(), error.description.Value(), error.raw); | 13 | error.module.Value(), error.description.Value(), error.raw); |
| 14 | } | 14 | } |
| 15 | 15 | ||
| 16 | void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::seconds time, | 16 | void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::seconds time, |
| 17 | std::function<void()> finished) const { | 17 | FinishedCallback finished) const { |
| 18 | LOG_CRITICAL( | 18 | LOG_CRITICAL( |
| 19 | Service_Fatal, | 19 | Service_Fatal, |
| 20 | "Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}", | 20 | "Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}", |
| @@ -23,7 +23,7 @@ void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::secon | |||
| 23 | 23 | ||
| 24 | void DefaultErrorApplet::ShowCustomErrorText(Result error, std::string main_text, | 24 | void DefaultErrorApplet::ShowCustomErrorText(Result error, std::string main_text, |
| 25 | std::string detail_text, | 25 | std::string detail_text, |
| 26 | std::function<void()> finished) const { | 26 | FinishedCallback finished) const { |
| 27 | LOG_CRITICAL(Service_Fatal, | 27 | LOG_CRITICAL(Service_Fatal, |
| 28 | "Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})", | 28 | "Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})", |
| 29 | error.module.Value(), error.description.Value(), error.raw); | 29 | error.module.Value(), error.description.Value(), error.raw); |
diff --git a/src/core/frontend/applets/error.h b/src/core/frontend/applets/error.h index f378f8805..884f2f653 100644 --- a/src/core/frontend/applets/error.h +++ b/src/core/frontend/applets/error.h | |||
| @@ -12,25 +12,27 @@ namespace Core::Frontend { | |||
| 12 | 12 | ||
| 13 | class ErrorApplet { | 13 | class ErrorApplet { |
| 14 | public: | 14 | public: |
| 15 | using FinishedCallback = std::function<void()>; | ||
| 16 | |||
| 15 | virtual ~ErrorApplet(); | 17 | virtual ~ErrorApplet(); |
| 16 | 18 | ||
| 17 | virtual void ShowError(Result error, std::function<void()> finished) const = 0; | 19 | virtual void ShowError(Result error, FinishedCallback finished) const = 0; |
| 18 | 20 | ||
| 19 | virtual void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, | 21 | virtual void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, |
| 20 | std::function<void()> finished) const = 0; | 22 | FinishedCallback finished) const = 0; |
| 21 | 23 | ||
| 22 | virtual void ShowCustomErrorText(Result error, std::string dialog_text, | 24 | virtual void ShowCustomErrorText(Result error, std::string dialog_text, |
| 23 | std::string fullscreen_text, | 25 | std::string fullscreen_text, |
| 24 | std::function<void()> finished) const = 0; | 26 | FinishedCallback finished) const = 0; |
| 25 | }; | 27 | }; |
| 26 | 28 | ||
| 27 | class DefaultErrorApplet final : public ErrorApplet { | 29 | class DefaultErrorApplet final : public ErrorApplet { |
| 28 | public: | 30 | public: |
| 29 | void ShowError(Result error, std::function<void()> finished) const override; | 31 | void ShowError(Result error, FinishedCallback finished) const override; |
| 30 | void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, | 32 | void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, |
| 31 | std::function<void()> finished) const override; | 33 | FinishedCallback finished) const override; |
| 32 | void ShowCustomErrorText(Result error, std::string main_text, std::string detail_text, | 34 | void ShowCustomErrorText(Result error, std::string main_text, std::string detail_text, |
| 33 | std::function<void()> finished) const override; | 35 | FinishedCallback finished) const override; |
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| 36 | } // namespace Core::Frontend | 38 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/mii_edit.cpp b/src/core/frontend/applets/mii_edit.cpp index d37b5368a..bc8c57067 100644 --- a/src/core/frontend/applets/mii_edit.cpp +++ b/src/core/frontend/applets/mii_edit.cpp | |||
| @@ -8,7 +8,7 @@ namespace Core::Frontend { | |||
| 8 | 8 | ||
| 9 | MiiEditApplet::~MiiEditApplet() = default; | 9 | MiiEditApplet::~MiiEditApplet() = default; |
| 10 | 10 | ||
| 11 | void DefaultMiiEditApplet::ShowMiiEdit(const std::function<void()>& callback) const { | 11 | void DefaultMiiEditApplet::ShowMiiEdit(const MiiEditCallback& callback) const { |
| 12 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 12 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 13 | 13 | ||
| 14 | callback(); | 14 | callback(); |
diff --git a/src/core/frontend/applets/mii_edit.h b/src/core/frontend/applets/mii_edit.h index 58fa2039b..d828f06ec 100644 --- a/src/core/frontend/applets/mii_edit.h +++ b/src/core/frontend/applets/mii_edit.h | |||
| @@ -9,14 +9,16 @@ namespace Core::Frontend { | |||
| 9 | 9 | ||
| 10 | class MiiEditApplet { | 10 | class MiiEditApplet { |
| 11 | public: | 11 | public: |
| 12 | using MiiEditCallback = std::function<void()>; | ||
| 13 | |||
| 12 | virtual ~MiiEditApplet(); | 14 | virtual ~MiiEditApplet(); |
| 13 | 15 | ||
| 14 | virtual void ShowMiiEdit(const std::function<void()>& callback) const = 0; | 16 | virtual void ShowMiiEdit(const MiiEditCallback& callback) const = 0; |
| 15 | }; | 17 | }; |
| 16 | 18 | ||
| 17 | class DefaultMiiEditApplet final : public MiiEditApplet { | 19 | class DefaultMiiEditApplet final : public MiiEditApplet { |
| 18 | public: | 20 | public: |
| 19 | void ShowMiiEdit(const std::function<void()>& callback) const override; | 21 | void ShowMiiEdit(const MiiEditCallback& callback) const override; |
| 20 | }; | 22 | }; |
| 21 | 23 | ||
| 22 | } // namespace Core::Frontend | 24 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp index d11fbce0a..da4cfbf87 100644 --- a/src/core/frontend/applets/profile_select.cpp +++ b/src/core/frontend/applets/profile_select.cpp | |||
| @@ -9,8 +9,7 @@ namespace Core::Frontend { | |||
| 9 | 9 | ||
| 10 | ProfileSelectApplet::~ProfileSelectApplet() = default; | 10 | ProfileSelectApplet::~ProfileSelectApplet() = default; |
| 11 | 11 | ||
| 12 | void DefaultProfileSelectApplet::SelectProfile( | 12 | void DefaultProfileSelectApplet::SelectProfile(SelectProfileCallback callback) const { |
| 13 | std::function<void(std::optional<Common::UUID>)> callback) const { | ||
| 14 | Service::Account::ProfileManager manager; | 13 | Service::Account::ProfileManager manager; |
| 15 | callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{})); | 14 | callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{})); |
| 16 | LOG_INFO(Service_ACC, "called, selecting current user instead of prompting..."); | 15 | LOG_INFO(Service_ACC, "called, selecting current user instead of prompting..."); |
diff --git a/src/core/frontend/applets/profile_select.h b/src/core/frontend/applets/profile_select.h index 8d6ee5279..138429533 100644 --- a/src/core/frontend/applets/profile_select.h +++ b/src/core/frontend/applets/profile_select.h | |||
| @@ -11,14 +11,16 @@ namespace Core::Frontend { | |||
| 11 | 11 | ||
| 12 | class ProfileSelectApplet { | 12 | class ProfileSelectApplet { |
| 13 | public: | 13 | public: |
| 14 | using SelectProfileCallback = std::function<void(std::optional<Common::UUID>)>; | ||
| 15 | |||
| 14 | virtual ~ProfileSelectApplet(); | 16 | virtual ~ProfileSelectApplet(); |
| 15 | 17 | ||
| 16 | virtual void SelectProfile(std::function<void(std::optional<Common::UUID>)> callback) const = 0; | 18 | virtual void SelectProfile(SelectProfileCallback callback) const = 0; |
| 17 | }; | 19 | }; |
| 18 | 20 | ||
| 19 | class DefaultProfileSelectApplet final : public ProfileSelectApplet { | 21 | class DefaultProfileSelectApplet final : public ProfileSelectApplet { |
| 20 | public: | 22 | public: |
| 21 | void SelectProfile(std::function<void(std::optional<Common::UUID>)> callback) const override; | 23 | void SelectProfile(SelectProfileCallback callback) const override; |
| 22 | }; | 24 | }; |
| 23 | 25 | ||
| 24 | } // namespace Core::Frontend | 26 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/software_keyboard.cpp b/src/core/frontend/applets/software_keyboard.cpp index 020c7fa5e..a3720f4d7 100644 --- a/src/core/frontend/applets/software_keyboard.cpp +++ b/src/core/frontend/applets/software_keyboard.cpp | |||
| @@ -15,10 +15,7 @@ DefaultSoftwareKeyboardApplet::~DefaultSoftwareKeyboardApplet() = default; | |||
| 15 | 15 | ||
| 16 | void DefaultSoftwareKeyboardApplet::InitializeKeyboard( | 16 | void DefaultSoftwareKeyboardApplet::InitializeKeyboard( |
| 17 | bool is_inline, KeyboardInitializeParameters initialize_parameters, | 17 | bool is_inline, KeyboardInitializeParameters initialize_parameters, |
| 18 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> | 18 | SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) { |
| 19 | submit_normal_callback_, | ||
| 20 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 21 | submit_inline_callback_) { | ||
| 22 | if (is_inline) { | 19 | if (is_inline) { |
| 23 | LOG_WARNING( | 20 | LOG_WARNING( |
| 24 | Service_AM, | 21 | Service_AM, |
diff --git a/src/core/frontend/applets/software_keyboard.h b/src/core/frontend/applets/software_keyboard.h index 094d1e713..8aef103d3 100644 --- a/src/core/frontend/applets/software_keyboard.h +++ b/src/core/frontend/applets/software_keyboard.h | |||
| @@ -54,14 +54,17 @@ struct InlineTextParameters { | |||
| 54 | 54 | ||
| 55 | class SoftwareKeyboardApplet { | 55 | class SoftwareKeyboardApplet { |
| 56 | public: | 56 | public: |
| 57 | using SubmitInlineCallback = | ||
| 58 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)>; | ||
| 59 | using SubmitNormalCallback = | ||
| 60 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)>; | ||
| 61 | |||
| 57 | virtual ~SoftwareKeyboardApplet(); | 62 | virtual ~SoftwareKeyboardApplet(); |
| 58 | 63 | ||
| 59 | virtual void InitializeKeyboard( | 64 | virtual void InitializeKeyboard(bool is_inline, |
| 60 | bool is_inline, KeyboardInitializeParameters initialize_parameters, | 65 | KeyboardInitializeParameters initialize_parameters, |
| 61 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> | 66 | SubmitNormalCallback submit_normal_callback_, |
| 62 | submit_normal_callback_, | 67 | SubmitInlineCallback submit_inline_callback_) = 0; |
| 63 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 64 | submit_inline_callback_) = 0; | ||
| 65 | 68 | ||
| 66 | virtual void ShowNormalKeyboard() const = 0; | 69 | virtual void ShowNormalKeyboard() const = 0; |
| 67 | 70 | ||
| @@ -81,12 +84,9 @@ class DefaultSoftwareKeyboardApplet final : public SoftwareKeyboardApplet { | |||
| 81 | public: | 84 | public: |
| 82 | ~DefaultSoftwareKeyboardApplet() override; | 85 | ~DefaultSoftwareKeyboardApplet() override; |
| 83 | 86 | ||
| 84 | void InitializeKeyboard( | 87 | void InitializeKeyboard(bool is_inline, KeyboardInitializeParameters initialize_parameters, |
| 85 | bool is_inline, KeyboardInitializeParameters initialize_parameters, | 88 | SubmitNormalCallback submit_normal_callback_, |
| 86 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> | 89 | SubmitInlineCallback submit_inline_callback_) override; |
| 87 | submit_normal_callback_, | ||
| 88 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 89 | submit_inline_callback_) override; | ||
| 90 | 90 | ||
| 91 | void ShowNormalKeyboard() const override; | 91 | void ShowNormalKeyboard() const override; |
| 92 | 92 | ||
| @@ -105,12 +105,10 @@ private: | |||
| 105 | void SubmitNormalText(std::u16string text) const; | 105 | void SubmitNormalText(std::u16string text) const; |
| 106 | void SubmitInlineText(std::u16string_view text) const; | 106 | void SubmitInlineText(std::u16string_view text) const; |
| 107 | 107 | ||
| 108 | KeyboardInitializeParameters parameters; | 108 | KeyboardInitializeParameters parameters{}; |
| 109 | 109 | ||
| 110 | mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> | 110 | mutable SubmitNormalCallback submit_normal_callback; |
| 111 | submit_normal_callback; | 111 | mutable SubmitInlineCallback submit_inline_callback; |
| 112 | mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 113 | submit_inline_callback; | ||
| 114 | }; | 112 | }; |
| 115 | 113 | ||
| 116 | } // namespace Core::Frontend | 114 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp index 27c7086be..b09cb7102 100644 --- a/src/core/frontend/applets/web_browser.cpp +++ b/src/core/frontend/applets/web_browser.cpp | |||
| @@ -10,18 +10,17 @@ WebBrowserApplet::~WebBrowserApplet() = default; | |||
| 10 | 10 | ||
| 11 | DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; | 11 | DefaultWebBrowserApplet::~DefaultWebBrowserApplet() = default; |
| 12 | 12 | ||
| 13 | void DefaultWebBrowserApplet::OpenLocalWebPage( | 13 | void DefaultWebBrowserApplet::OpenLocalWebPage(const std::string& local_url, |
| 14 | const std::string& local_url, std::function<void()> extract_romfs_callback, | 14 | ExtractROMFSCallback extract_romfs_callback, |
| 15 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { | 15 | OpenWebPageCallback callback) const { |
| 16 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", | 16 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open local web page at {}", |
| 17 | local_url); | 17 | local_url); |
| 18 | 18 | ||
| 19 | callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); | 19 | callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/"); |
| 20 | } | 20 | } |
| 21 | 21 | ||
| 22 | void DefaultWebBrowserApplet::OpenExternalWebPage( | 22 | void DefaultWebBrowserApplet::OpenExternalWebPage(const std::string& external_url, |
| 23 | const std::string& external_url, | 23 | OpenWebPageCallback callback) const { |
| 24 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const { | ||
| 25 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}", | 24 | LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}", |
| 26 | external_url); | 25 | external_url); |
| 27 | 26 | ||
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h index 1411274f8..4f72284ad 100644 --- a/src/core/frontend/applets/web_browser.h +++ b/src/core/frontend/applets/web_browser.h | |||
| @@ -11,29 +11,29 @@ namespace Core::Frontend { | |||
| 11 | 11 | ||
| 12 | class WebBrowserApplet { | 12 | class WebBrowserApplet { |
| 13 | public: | 13 | public: |
| 14 | using ExtractROMFSCallback = std::function<void()>; | ||
| 15 | using OpenWebPageCallback = | ||
| 16 | std::function<void(Service::AM::Applets::WebExitReason, std::string)>; | ||
| 17 | |||
| 14 | virtual ~WebBrowserApplet(); | 18 | virtual ~WebBrowserApplet(); |
| 15 | 19 | ||
| 16 | virtual void OpenLocalWebPage( | 20 | virtual void OpenLocalWebPage(const std::string& local_url, |
| 17 | const std::string& local_url, std::function<void()> extract_romfs_callback, | 21 | ExtractROMFSCallback extract_romfs_callback, |
| 18 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; | 22 | OpenWebPageCallback callback) const = 0; |
| 19 | 23 | ||
| 20 | virtual void OpenExternalWebPage( | 24 | virtual void OpenExternalWebPage(const std::string& external_url, |
| 21 | const std::string& external_url, | 25 | OpenWebPageCallback callback) const = 0; |
| 22 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0; | ||
| 23 | }; | 26 | }; |
| 24 | 27 | ||
| 25 | class DefaultWebBrowserApplet final : public WebBrowserApplet { | 28 | class DefaultWebBrowserApplet final : public WebBrowserApplet { |
| 26 | public: | 29 | public: |
| 27 | ~DefaultWebBrowserApplet() override; | 30 | ~DefaultWebBrowserApplet() override; |
| 28 | 31 | ||
| 29 | void OpenLocalWebPage(const std::string& local_url, | 32 | void OpenLocalWebPage(const std::string& local_url, ExtractROMFSCallback extract_romfs_callback, |
| 30 | std::function<void()> extract_romfs_callback, | 33 | OpenWebPageCallback callback) const override; |
| 31 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | ||
| 32 | callback) const override; | ||
| 33 | 34 | ||
| 34 | void OpenExternalWebPage(const std::string& external_url, | 35 | void OpenExternalWebPage(const std::string& external_url, |
| 35 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | 36 | OpenWebPageCallback callback) const override; |
| 36 | callback) const override; | ||
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | } // namespace Core::Frontend | 39 | } // namespace Core::Frontend |
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index ac1906d5e..95363b645 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -17,6 +17,8 @@ enum class WindowSystemType { | |||
| 17 | Windows, | 17 | Windows, |
| 18 | X11, | 18 | X11, |
| 19 | Wayland, | 19 | Wayland, |
| 20 | Cocoa, | ||
| 21 | Android, | ||
| 20 | }; | 22 | }; |
| 21 | 23 | ||
| 22 | /** | 24 | /** |
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index b6c8cc58d..30c2e9d17 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp | |||
| @@ -37,7 +37,7 @@ void EmulatedConsole::SetTouchParams() { | |||
| 37 | touchscreen_param.Set("axis_x", i * 2); | 37 | touchscreen_param.Set("axis_x", i * 2); |
| 38 | touchscreen_param.Set("axis_y", (i * 2) + 1); | 38 | touchscreen_param.Set("axis_y", (i * 2) + 1); |
| 39 | touchscreen_param.Set("button", i); | 39 | touchscreen_param.Set("button", i); |
| 40 | touch_params[index++] = touchscreen_param; | 40 | touch_params[index++] = std::move(touchscreen_param); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | const auto button_index = | 43 | const auto button_index = |
| @@ -59,7 +59,7 @@ void EmulatedConsole::SetTouchParams() { | |||
| 59 | touch_button_params.Set("button", params.Serialize()); | 59 | touch_button_params.Set("button", params.Serialize()); |
| 60 | touch_button_params.Set("x", x); | 60 | touch_button_params.Set("x", x); |
| 61 | touch_button_params.Set("y", y); | 61 | touch_button_params.Set("y", y); |
| 62 | touch_params[index] = touch_button_params; | 62 | touch_params[index] = std::move(touch_button_params); |
| 63 | index++; | 63 | index++; |
| 64 | } | 64 | } |
| 65 | } | 65 | } |
| @@ -131,7 +131,7 @@ Common::ParamPackage EmulatedConsole::GetMotionParam() const { | |||
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { | 133 | void EmulatedConsole::SetMotionParam(Common::ParamPackage param) { |
| 134 | motion_params = param; | 134 | motion_params = std::move(param); |
| 135 | ReloadInput(); | 135 | ReloadInput(); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| @@ -199,7 +199,7 @@ void EmulatedConsole::SetTouch(const Common::Input::CallbackStatus& callback, st | |||
| 199 | 199 | ||
| 200 | if (is_new_input) { | 200 | if (is_new_input) { |
| 201 | touch_value.pressed.value = true; | 201 | touch_value.pressed.value = true; |
| 202 | touch_value.id = static_cast<u32>(index); | 202 | touch_value.id = static_cast<int>(index); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | touch_value.x = touch_input.x; | 205 | touch_value.x = touch_input.x; |
| @@ -284,7 +284,7 @@ void EmulatedConsole::TriggerOnChange(ConsoleTriggerType type) { | |||
| 284 | 284 | ||
| 285 | int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { | 285 | int EmulatedConsole::SetCallback(ConsoleUpdateCallback update_callback) { |
| 286 | std::scoped_lock lock{callback_mutex}; | 286 | std::scoped_lock lock{callback_mutex}; |
| 287 | callback_list.insert_or_assign(last_callback_key, update_callback); | 287 | callback_list.insert_or_assign(last_callback_key, std::move(update_callback)); |
| 288 | return last_callback_key++; | 288 | return last_callback_key++; |
| 289 | } | 289 | } |
| 290 | 290 | ||
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index c96d9eef3..67969e938 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | 5 | ||
| 6 | #include "common/polyfill_ranges.h" | ||
| 6 | #include "common/thread.h" | 7 | #include "common/thread.h" |
| 7 | #include "core/hid/emulated_controller.h" | 8 | #include "core/hid/emulated_controller.h" |
| 8 | #include "core/hid/input_converter.h" | 9 | #include "core/hid/input_converter.h" |
| @@ -109,10 +110,9 @@ void EmulatedController::ReloadFromSettings() { | |||
| 109 | original_npad_type = npad_type; | 110 | original_npad_type = npad_type; |
| 110 | } | 111 | } |
| 111 | 112 | ||
| 113 | Disconnect(); | ||
| 112 | if (player.connected) { | 114 | if (player.connected) { |
| 113 | Connect(); | 115 | Connect(); |
| 114 | } else { | ||
| 115 | Disconnect(); | ||
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | ReloadInput(); | 118 | ReloadInput(); |
| @@ -424,15 +424,14 @@ void EmulatedController::RestoreConfig() { | |||
| 424 | ReloadFromSettings(); | 424 | ReloadFromSettings(); |
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices( | 427 | std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices() const { |
| 428 | EmulatedDeviceIndex device_index) const { | ||
| 429 | std::vector<Common::ParamPackage> devices; | 428 | std::vector<Common::ParamPackage> devices; |
| 430 | for (const auto& param : button_params) { | 429 | for (const auto& param : button_params) { |
| 431 | if (!param.Has("engine")) { | 430 | if (!param.Has("engine")) { |
| 432 | continue; | 431 | continue; |
| 433 | } | 432 | } |
| 434 | const auto devices_it = std::find_if( | 433 | const auto devices_it = std::find_if( |
| 435 | devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { | 434 | devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) { |
| 436 | return param.Get("engine", "") == param_.Get("engine", "") && | 435 | return param.Get("engine", "") == param_.Get("engine", "") && |
| 437 | param.Get("guid", "") == param_.Get("guid", "") && | 436 | param.Get("guid", "") == param_.Get("guid", "") && |
| 438 | param.Get("port", 0) == param_.Get("port", 0) && | 437 | param.Get("port", 0) == param_.Get("port", 0) && |
| @@ -441,12 +440,12 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices( | |||
| 441 | if (devices_it != devices.end()) { | 440 | if (devices_it != devices.end()) { |
| 442 | continue; | 441 | continue; |
| 443 | } | 442 | } |
| 444 | Common::ParamPackage device{}; | 443 | |
| 444 | auto& device = devices.emplace_back(); | ||
| 445 | device.Set("engine", param.Get("engine", "")); | 445 | device.Set("engine", param.Get("engine", "")); |
| 446 | device.Set("guid", param.Get("guid", "")); | 446 | device.Set("guid", param.Get("guid", "")); |
| 447 | device.Set("port", param.Get("port", 0)); | 447 | device.Set("port", param.Get("port", 0)); |
| 448 | device.Set("pad", param.Get("pad", 0)); | 448 | device.Set("pad", param.Get("pad", 0)); |
| 449 | devices.push_back(device); | ||
| 450 | } | 449 | } |
| 451 | 450 | ||
| 452 | for (const auto& param : stick_params) { | 451 | for (const auto& param : stick_params) { |
| @@ -457,7 +456,7 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices( | |||
| 457 | continue; | 456 | continue; |
| 458 | } | 457 | } |
| 459 | const auto devices_it = std::find_if( | 458 | const auto devices_it = std::find_if( |
| 460 | devices.begin(), devices.end(), [param](const Common::ParamPackage param_) { | 459 | devices.begin(), devices.end(), [¶m](const Common::ParamPackage& param_) { |
| 461 | return param.Get("engine", "") == param_.Get("engine", "") && | 460 | return param.Get("engine", "") == param_.Get("engine", "") && |
| 462 | param.Get("guid", "") == param_.Get("guid", "") && | 461 | param.Get("guid", "") == param_.Get("guid", "") && |
| 463 | param.Get("port", 0) == param_.Get("port", 0) && | 462 | param.Get("port", 0) == param_.Get("port", 0) && |
| @@ -466,12 +465,12 @@ std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices( | |||
| 466 | if (devices_it != devices.end()) { | 465 | if (devices_it != devices.end()) { |
| 467 | continue; | 466 | continue; |
| 468 | } | 467 | } |
| 469 | Common::ParamPackage device{}; | 468 | |
| 469 | auto& device = devices.emplace_back(); | ||
| 470 | device.Set("engine", param.Get("engine", "")); | 470 | device.Set("engine", param.Get("engine", "")); |
| 471 | device.Set("guid", param.Get("guid", "")); | 471 | device.Set("guid", param.Get("guid", "")); |
| 472 | device.Set("port", param.Get("port", 0)); | 472 | device.Set("port", param.Get("port", 0)); |
| 473 | device.Set("pad", param.Get("pad", 0)); | 473 | device.Set("pad", param.Get("pad", 0)); |
| 474 | devices.push_back(device); | ||
| 475 | } | 474 | } |
| 476 | return devices; | 475 | return devices; |
| 477 | } | 476 | } |
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index d004ca56a..fa7a34278 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <unordered_map> | 10 | #include <unordered_map> |
| 11 | #include <vector> | ||
| 11 | 12 | ||
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 13 | #include "common/input.h" | 14 | #include "common/input.h" |
| @@ -243,7 +244,7 @@ public: | |||
| 243 | void RestoreConfig(); | 244 | void RestoreConfig(); |
| 244 | 245 | ||
| 245 | /// Returns a vector of mapped devices from the mapped button and stick parameters | 246 | /// Returns a vector of mapped devices from the mapped button and stick parameters |
| 246 | std::vector<Common::ParamPackage> GetMappedDevices(EmulatedDeviceIndex device_index) const; | 247 | std::vector<Common::ParamPackage> GetMappedDevices() const; |
| 247 | 248 | ||
| 248 | // Returns the current mapped button device | 249 | // Returns the current mapped button device |
| 249 | Common::ParamPackage GetButtonParam(std::size_t index) const; | 250 | Common::ParamPackage GetButtonParam(std::size_t index) const; |
diff --git a/src/core/hid/emulated_devices.h b/src/core/hid/emulated_devices.h index 4149eeced..4cdbf9dc6 100644 --- a/src/core/hid/emulated_devices.h +++ b/src/core/hid/emulated_devices.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <unordered_map> | 10 | #include <unordered_map> |
| 11 | #include <vector> | ||
| 11 | 12 | ||
| 12 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 13 | #include "common/input.h" | 14 | #include "common/input.h" |
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index 3b6e7baff..87ca65592 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h | |||
| @@ -280,18 +280,19 @@ struct KMemoryInfo { | |||
| 280 | 280 | ||
| 281 | class KMemoryBlock : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock> { | 281 | class KMemoryBlock : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock> { |
| 282 | private: | 282 | private: |
| 283 | u16 m_device_disable_merge_left_count; | 283 | u16 m_device_disable_merge_left_count{}; |
| 284 | u16 m_device_disable_merge_right_count; | 284 | u16 m_device_disable_merge_right_count{}; |
| 285 | VAddr m_address; | 285 | VAddr m_address{}; |
| 286 | size_t m_num_pages; | 286 | size_t m_num_pages{}; |
| 287 | KMemoryState m_memory_state; | 287 | KMemoryState m_memory_state{KMemoryState::None}; |
| 288 | u16 m_ipc_lock_count; | 288 | u16 m_ipc_lock_count{}; |
| 289 | u16 m_device_use_count; | 289 | u16 m_device_use_count{}; |
| 290 | u16 m_ipc_disable_merge_count; | 290 | u16 m_ipc_disable_merge_count{}; |
| 291 | KMemoryPermission m_permission; | 291 | KMemoryPermission m_permission{KMemoryPermission::None}; |
| 292 | KMemoryPermission m_original_permission; | 292 | KMemoryPermission m_original_permission{KMemoryPermission::None}; |
| 293 | KMemoryAttribute m_attribute; | 293 | KMemoryAttribute m_attribute{KMemoryAttribute::None}; |
| 294 | KMemoryBlockDisableMergeAttribute m_disable_merge_attribute; | 294 | KMemoryBlockDisableMergeAttribute m_disable_merge_attribute{ |
| 295 | KMemoryBlockDisableMergeAttribute::None}; | ||
| 295 | 296 | ||
| 296 | public: | 297 | public: |
| 297 | static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) { | 298 | static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) { |
| @@ -367,12 +368,8 @@ public: | |||
| 367 | 368 | ||
| 368 | constexpr KMemoryBlock(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, | 369 | constexpr KMemoryBlock(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, |
| 369 | KMemoryAttribute attr) | 370 | KMemoryAttribute attr) |
| 370 | : Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(), | 371 | : Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(), m_address(addr), m_num_pages(np), |
| 371 | m_device_disable_merge_left_count(), m_device_disable_merge_right_count(), | 372 | m_memory_state(ms), m_permission(p), m_attribute(attr) {} |
| 372 | m_address(addr), m_num_pages(np), m_memory_state(ms), m_ipc_lock_count(0), | ||
| 373 | m_device_use_count(0), m_ipc_disable_merge_count(), m_permission(p), | ||
| 374 | m_original_permission(KMemoryPermission::None), m_attribute(attr), | ||
| 375 | m_disable_merge_attribute() {} | ||
| 376 | 373 | ||
| 377 | constexpr void Initialize(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, | 374 | constexpr void Initialize(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p, |
| 378 | KMemoryAttribute attr) { | 375 | KMemoryAttribute attr) { |
diff --git a/src/core/hle/kernel/k_memory_block_manager.h b/src/core/hle/kernel/k_memory_block_manager.h index 9b5873883..d382722a6 100644 --- a/src/core/hle/kernel/k_memory_block_manager.h +++ b/src/core/hle/kernel/k_memory_block_manager.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <array> | ||
| 6 | #include <functional> | 7 | #include <functional> |
| 7 | 8 | ||
| 8 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| @@ -17,9 +18,9 @@ public: | |||
| 17 | static constexpr size_t MaxBlocks = 2; | 18 | static constexpr size_t MaxBlocks = 2; |
| 18 | 19 | ||
| 19 | private: | 20 | private: |
| 20 | KMemoryBlock* m_blocks[MaxBlocks]; | 21 | std::array<KMemoryBlock*, MaxBlocks> m_blocks{}; |
| 21 | size_t m_index; | 22 | size_t m_index{MaxBlocks}; |
| 22 | KMemoryBlockSlabManager* m_slab_manager; | 23 | KMemoryBlockSlabManager* m_slab_manager{}; |
| 23 | 24 | ||
| 24 | private: | 25 | private: |
| 25 | Result Initialize(size_t num_blocks) { | 26 | Result Initialize(size_t num_blocks) { |
| @@ -41,7 +42,7 @@ private: | |||
| 41 | public: | 42 | public: |
| 42 | KMemoryBlockManagerUpdateAllocator(Result* out_result, KMemoryBlockSlabManager* sm, | 43 | KMemoryBlockManagerUpdateAllocator(Result* out_result, KMemoryBlockSlabManager* sm, |
| 43 | size_t num_blocks = MaxBlocks) | 44 | size_t num_blocks = MaxBlocks) |
| 44 | : m_blocks(), m_index(MaxBlocks), m_slab_manager(sm) { | 45 | : m_slab_manager(sm) { |
| 45 | *out_result = this->Initialize(num_blocks); | 46 | *out_result = this->Initialize(num_blocks); |
| 46 | } | 47 | } |
| 47 | 48 | ||
diff --git a/src/core/hle/kernel/k_memory_manager.cpp b/src/core/hle/kernel/k_memory_manager.cpp index c4bf306e8..bd33571da 100644 --- a/src/core/hle/kernel/k_memory_manager.cpp +++ b/src/core/hle/kernel/k_memory_manager.cpp | |||
| @@ -225,8 +225,8 @@ Result KMemoryManager::AllocatePageGroupImpl(KPageGroup* out, size_t num_pages, | |||
| 225 | ON_RESULT_FAILURE { | 225 | ON_RESULT_FAILURE { |
| 226 | for (const auto& it : out->Nodes()) { | 226 | for (const auto& it : out->Nodes()) { |
| 227 | auto& manager = this->GetManager(it.GetAddress()); | 227 | auto& manager = this->GetManager(it.GetAddress()); |
| 228 | const size_t node_num_pages = | 228 | const size_t node_num_pages = std::min<u64>( |
| 229 | std::min(it.GetNumPages(), (manager.GetEndAddress() - it.GetAddress()) / PageSize); | 229 | it.GetNumPages(), (manager.GetEndAddress() - it.GetAddress()) / PageSize); |
| 230 | manager.Free(it.GetAddress(), node_num_pages); | 230 | manager.Free(it.GetAddress(), node_num_pages); |
| 231 | } | 231 | } |
| 232 | out->Finalize(); | 232 | out->Finalize(); |
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 5620c3660..a96c55a3e 100644 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h | |||
| @@ -74,7 +74,7 @@ public: | |||
| 74 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} | 74 | static void PostDestroy([[maybe_unused]] uintptr_t arg) {} |
| 75 | 75 | ||
| 76 | private: | 76 | private: |
| 77 | Core::DeviceMemory* device_memory; | 77 | Core::DeviceMemory* device_memory{}; |
| 78 | KProcess* owner_process{}; | 78 | KProcess* owner_process{}; |
| 79 | KPageGroup page_list; | 79 | KPageGroup page_list; |
| 80 | Svc::MemoryPermission owner_permission{}; | 80 | Svc::MemoryPermission owner_permission{}; |
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h index a8c77a7d4..68469b041 100644 --- a/src/core/hle/kernel/k_slab_heap.h +++ b/src/core/hle/kernel/k_slab_heap.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <atomic> | 6 | #include <atomic> |
| 7 | 7 | ||
| 8 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 9 | #include "common/atomic_ops.h" | ||
| 9 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 11 | #include "common/spin_lock.h" | 12 | #include "common/spin_lock.h" |
| @@ -82,16 +83,13 @@ private: | |||
| 82 | 83 | ||
| 83 | private: | 84 | private: |
| 84 | void UpdatePeakImpl(uintptr_t obj) { | 85 | void UpdatePeakImpl(uintptr_t obj) { |
| 85 | static_assert(std::atomic_ref<uintptr_t>::is_always_lock_free); | ||
| 86 | std::atomic_ref<uintptr_t> peak_ref(m_peak); | ||
| 87 | |||
| 88 | const uintptr_t alloc_peak = obj + this->GetObjectSize(); | 86 | const uintptr_t alloc_peak = obj + this->GetObjectSize(); |
| 89 | uintptr_t cur_peak = m_peak; | 87 | uintptr_t cur_peak = m_peak; |
| 90 | do { | 88 | do { |
| 91 | if (alloc_peak <= cur_peak) { | 89 | if (alloc_peak <= cur_peak) { |
| 92 | break; | 90 | break; |
| 93 | } | 91 | } |
| 94 | } while (!peak_ref.compare_exchange_strong(cur_peak, alloc_peak)); | 92 | } while (!Common::AtomicCompareAndSwap(&m_peak, alloc_peak, cur_peak, cur_peak)); |
| 95 | } | 93 | } |
| 96 | 94 | ||
| 97 | public: | 95 | public: |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index f38c92bff..dc52b4ed3 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -784,8 +784,8 @@ private: | |||
| 784 | std::vector<KSynchronizationObject*> wait_objects_for_debugging; | 784 | std::vector<KSynchronizationObject*> wait_objects_for_debugging; |
| 785 | VAddr mutex_wait_address_for_debugging{}; | 785 | VAddr mutex_wait_address_for_debugging{}; |
| 786 | ThreadWaitReasonForDebugging wait_reason_for_debugging{}; | 786 | ThreadWaitReasonForDebugging wait_reason_for_debugging{}; |
| 787 | uintptr_t argument; | 787 | uintptr_t argument{}; |
| 788 | VAddr stack_top; | 788 | VAddr stack_top{}; |
| 789 | 789 | ||
| 790 | public: | 790 | public: |
| 791 | using ConditionVariableThreadTreeType = ConditionVariableThreadTree; | 791 | using ConditionVariableThreadTreeType = ConditionVariableThreadTree; |
diff --git a/src/core/hle/kernel/k_thread_local_page.h b/src/core/hle/kernel/k_thread_local_page.h index 5d466ace7..fe0cff084 100644 --- a/src/core/hle/kernel/k_thread_local_page.h +++ b/src/core/hle/kernel/k_thread_local_page.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/intrusive_red_black_tree.h" | 12 | #include "common/intrusive_red_black_tree.h" |
| 13 | #include "common/polyfill_ranges.h" | ||
| 13 | #include "core/hle/kernel/memory_types.h" | 14 | #include "core/hle/kernel/memory_types.h" |
| 14 | #include "core/hle/kernel/slab_helpers.h" | 15 | #include "core/hle/kernel/slab_helpers.h" |
| 15 | #include "core/hle/result.h" | 16 | #include "core/hle/result.h" |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b77723503..288f97df5 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -891,7 +891,7 @@ struct KernelCore::Impl { | |||
| 891 | Common::ThreadWorker service_threads_manager; | 891 | Common::ThreadWorker service_threads_manager; |
| 892 | Common::Barrier service_thread_barrier; | 892 | Common::Barrier service_thread_barrier; |
| 893 | 893 | ||
| 894 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; | 894 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads{}; |
| 895 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; | 895 | std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; |
| 896 | 896 | ||
| 897 | bool is_multicore{}; | 897 | bool is_multicore{}; |
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index 2fc8d4be2..fb2ba4c6b 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h | |||
| @@ -85,7 +85,7 @@ private: | |||
| 85 | std::mutex guard; | 85 | std::mutex guard; |
| 86 | std::condition_variable on_interrupt; | 86 | std::condition_variable on_interrupt; |
| 87 | std::unique_ptr<Core::ARM_Interface> arm_interface; | 87 | std::unique_ptr<Core::ARM_Interface> arm_interface; |
| 88 | bool is_interrupted; | 88 | bool is_interrupted{}; |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | } // namespace Kernel | 91 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index e6e41ac34..e72c3d35d 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <thread> | 7 | #include <thread> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | 9 | ||
| 10 | #include "common/polyfill_thread.h" | ||
| 10 | #include "common/scope_exit.h" | 11 | #include "common/scope_exit.h" |
| 11 | #include "common/thread.h" | 12 | #include "common/thread.h" |
| 12 | #include "core/hle/ipc_helpers.h" | 13 | #include "core/hle/ipc_helpers.h" |
| @@ -35,14 +36,14 @@ public: | |||
| 35 | 36 | ||
| 36 | private: | 37 | private: |
| 37 | KernelCore& kernel; | 38 | KernelCore& kernel; |
| 38 | |||
| 39 | std::jthread m_host_thread; | ||
| 40 | std::mutex m_session_mutex; | ||
| 41 | std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions; | ||
| 42 | KEvent* m_wakeup_event; | ||
| 43 | KThread* m_thread; | ||
| 44 | std::atomic<bool> m_shutdown_requested; | ||
| 45 | const std::string m_service_name; | 39 | const std::string m_service_name; |
| 40 | |||
| 41 | std::jthread m_host_thread{}; | ||
| 42 | std::mutex m_session_mutex{}; | ||
| 43 | std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions{}; | ||
| 44 | KEvent* m_wakeup_event{}; | ||
| 45 | KThread* m_thread{}; | ||
| 46 | std::atomic<bool> m_shutdown_requested{}; | ||
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | void ServiceThread::Impl::WaitAndProcessImpl() { | 49 | void ServiceThread::Impl::WaitAndProcessImpl() { |
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 3730937fe..1ea8c7fbc 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h | |||
| @@ -82,7 +82,7 @@ void SvcWrap64(Core::System& system) { | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | // Used by ControlCodeMemory | 84 | // Used by ControlCodeMemory |
| 85 | template <Result func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)> | 85 | template <Result func(Core::System&, Handle, u32, VAddr, size_t, Svc::MemoryPermission)> |
| 86 | void SvcWrap64(Core::System& system) { | 86 | void SvcWrap64(Core::System& system) { |
| 87 | FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), | 87 | FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), |
| 88 | static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3), | 88 | static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3), |
| @@ -327,7 +327,7 @@ void SvcWrap64(Core::System& system) { | |||
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | // Used by CreateCodeMemory | 329 | // Used by CreateCodeMemory |
| 330 | template <Result func(Core::System&, Handle*, u64, u64)> | 330 | template <Result func(Core::System&, Handle*, VAddr, size_t)> |
| 331 | void SvcWrap64(Core::System& system) { | 331 | void SvcWrap64(Core::System& system) { |
| 332 | u32 param_1 = 0; | 332 | u32 param_1 = 0; |
| 333 | const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2)).raw; | 333 | const u32 retval = func(system, ¶m_1, Param(system, 1), Param(system, 2)).raw; |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 85a3f0802..6d1084fd1 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "common/fs/file.h" | 7 | #include "common/fs/file.h" |
| 8 | #include "common/fs/path_util.h" | 8 | #include "common/fs/path_util.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "common/string_util.h" | 11 | #include "common/string_util.h" |
| 11 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 12 | #include "core/constants.h" | 13 | #include "core/constants.h" |
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index 481e0d141..97f7c6688 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/fs/file.h" | 9 | #include "common/fs/file.h" |
| 10 | #include "common/fs/fs.h" | 10 | #include "common/fs/fs.h" |
| 11 | #include "common/fs/path_util.h" | 11 | #include "common/fs/path_util.h" |
| 12 | #include "common/polyfill_ranges.h" | ||
| 12 | #include "common/settings.h" | 13 | #include "common/settings.h" |
| 13 | #include "core/hle/service/acc/profile_manager.h" | 14 | #include "core/hle/service/acc/profile_manager.h" |
| 14 | 15 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 8ea7fd760..22999c942 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1125,7 +1125,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { | |||
| 1125 | 1125 | ||
| 1126 | const u64 offset{rp.Pop<u64>()}; | 1126 | const u64 offset{rp.Pop<u64>()}; |
| 1127 | const std::vector<u8> data{ctx.ReadBuffer()}; | 1127 | const std::vector<u8> data{ctx.ReadBuffer()}; |
| 1128 | const std::size_t size{std::min(data.size(), backing.GetSize() - offset)}; | 1128 | const std::size_t size{std::min<u64>(data.size(), backing.GetSize() - offset)}; |
| 1129 | 1129 | ||
| 1130 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | 1130 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); |
| 1131 | 1131 | ||
| @@ -1149,7 +1149,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { | |||
| 1149 | IPC::RequestParser rp{ctx}; | 1149 | IPC::RequestParser rp{ctx}; |
| 1150 | 1150 | ||
| 1151 | const u64 offset{rp.Pop<u64>()}; | 1151 | const u64 offset{rp.Pop<u64>()}; |
| 1152 | const std::size_t size{std::min(ctx.GetWriteBufferSize(), backing.GetSize() - offset)}; | 1152 | const std::size_t size{std::min<u64>(ctx.GetWriteBufferSize(), backing.GetSize() - offset)}; |
| 1153 | 1153 | ||
| 1154 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | 1154 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); |
| 1155 | 1155 | ||
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index 053e8f9dd..26dec7147 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp | |||
| @@ -203,9 +203,8 @@ private: | |||
| 203 | }; | 203 | }; |
| 204 | 204 | ||
| 205 | AudInU::AudInU(Core::System& system_) | 205 | AudInU::AudInU(Core::System& system_) |
| 206 | : ServiceFramework{system_, "audin:u", ServiceThreadType::CreateNew}, | 206 | : ServiceFramework{system_, "audin:u"}, service_context{system_, "AudInU"}, |
| 207 | service_context{system_, "AudInU"}, impl{std::make_unique<AudioCore::AudioIn::Manager>( | 207 | impl{std::make_unique<AudioCore::AudioIn::Manager>(system_)} { |
| 208 | system_)} { | ||
| 209 | // clang-format off | 208 | // clang-format off |
| 210 | static const FunctionInfo functions[] = { | 209 | static const FunctionInfo functions[] = { |
| 211 | {0, &AudInU::ListAudioIns, "ListAudioIns"}, | 210 | {0, &AudInU::ListAudioIns, "ListAudioIns"}, |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 29751f075..991e30ba1 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -26,9 +26,8 @@ public: | |||
| 26 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, | 26 | explicit IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, |
| 27 | size_t session_id, const std::string& device_name, | 27 | size_t session_id, const std::string& device_name, |
| 28 | const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) | 28 | const AudioOutParameter& in_params, u32 handle, u64 applet_resource_user_id) |
| 29 | : ServiceFramework{system_, "IAudioOut", ServiceThreadType::CreateNew}, | 29 | : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, |
| 30 | service_context{system_, "IAudioOut"}, event{service_context.CreateEvent( | 30 | event{service_context.CreateEvent("AudioOutEvent")}, |
| 31 | "AudioOutEvent")}, | ||
| 32 | impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { | 31 | impl{std::make_shared<AudioCore::AudioOut::Out>(system_, manager, event, session_id)} { |
| 33 | 32 | ||
| 34 | // clang-format off | 33 | // clang-format off |
| @@ -221,9 +220,8 @@ private: | |||
| 221 | }; | 220 | }; |
| 222 | 221 | ||
| 223 | AudOutU::AudOutU(Core::System& system_) | 222 | AudOutU::AudOutU(Core::System& system_) |
| 224 | : ServiceFramework{system_, "audout:u", ServiceThreadType::CreateNew}, | 223 | : ServiceFramework{system_, "audout:u"}, service_context{system_, "AudOutU"}, |
| 225 | service_context{system_, "AudOutU"}, impl{std::make_unique<AudioCore::AudioOut::Manager>( | 224 | impl{std::make_unique<AudioCore::AudioOut::Manager>(system_)} { |
| 226 | system_)} { | ||
| 227 | // clang-format off | 225 | // clang-format off |
| 228 | static const FunctionInfo functions[] = { | 226 | static const FunctionInfo functions[] = { |
| 229 | {0, &AudOutU::ListAudioOuts, "ListAudioOuts"}, | 227 | {0, &AudOutU::ListAudioOuts, "ListAudioOuts"}, |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 034ee273f..ead16c321 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "common/bit_util.h" | 14 | #include "common/bit_util.h" |
| 15 | #include "common/common_funcs.h" | 15 | #include "common/common_funcs.h" |
| 16 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 17 | #include "common/polyfill_ranges.h" | ||
| 17 | #include "common/string_util.h" | 18 | #include "common/string_util.h" |
| 18 | #include "core/core.h" | 19 | #include "core/core.h" |
| 19 | #include "core/hle/ipc_helpers.h" | 20 | #include "core/hle/ipc_helpers.h" |
| @@ -34,10 +35,9 @@ public: | |||
| 34 | AudioCore::AudioRendererParameterInternal& params, | 35 | AudioCore::AudioRendererParameterInternal& params, |
| 35 | Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, | 36 | Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, |
| 36 | u32 process_handle, u64 applet_resource_user_id, s32 session_id) | 37 | u32 process_handle, u64 applet_resource_user_id, s32 session_id) |
| 37 | : ServiceFramework{system_, "IAudioRenderer", ServiceThreadType::CreateNew}, | 38 | : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, |
| 38 | service_context{system_, "IAudioRenderer"}, rendered_event{service_context.CreateEvent( | 39 | rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, |
| 39 | "IAudioRendererEvent")}, | 40 | impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { |
| 40 | manager{manager_}, impl{std::make_unique<Renderer>(system_, manager, rendered_event)} { | ||
| 41 | // clang-format off | 41 | // clang-format off |
| 42 | static const FunctionInfo functions[] = { | 42 | static const FunctionInfo functions[] = { |
| 43 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, | 43 | {0, &IAudioRenderer::GetSampleRate, "GetSampleRate"}, |
| @@ -242,10 +242,8 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> { | |||
| 242 | public: | 242 | public: |
| 243 | explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision, | 243 | explicit IAudioDevice(Core::System& system_, u64 applet_resource_user_id, u32 revision, |
| 244 | u32 device_num) | 244 | u32 device_num) |
| 245 | : ServiceFramework{system_, "IAudioDevice", ServiceThreadType::CreateNew}, | 245 | : ServiceFramework{system_, "IAudioDevice"}, service_context{system_, "IAudioDevice"}, |
| 246 | service_context{system_, "IAudioDevice"}, impl{std::make_unique<AudioDevice>( | 246 | impl{std::make_unique<AudioDevice>(system_, applet_resource_user_id, revision)}, |
| 247 | system_, applet_resource_user_id, | ||
| 248 | revision)}, | ||
| 249 | event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} { | 247 | event{service_context.CreateEvent(fmt::format("IAudioDeviceEvent-{}", device_num))} { |
| 250 | static const FunctionInfo functions[] = { | 248 | static const FunctionInfo functions[] = { |
| 251 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, | 249 | {0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"}, |
| @@ -420,7 +418,7 @@ private: | |||
| 420 | }; | 418 | }; |
| 421 | 419 | ||
| 422 | AudRenU::AudRenU(Core::System& system_) | 420 | AudRenU::AudRenU(Core::System& system_) |
| 423 | : ServiceFramework{system_, "audren:u", ServiceThreadType::CreateNew}, | 421 | : ServiceFramework{system_, "audren:u"}, |
| 424 | service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} { | 422 | service_context{system_, "audren:u"}, impl{std::make_unique<Manager>(system_)} { |
| 425 | // clang-format off | 423 | // clang-format off |
| 426 | static const FunctionInfo functions[] = { | 424 | static const FunctionInfo functions[] = { |
diff --git a/src/core/hle/service/nfc/mifare_user.cpp b/src/core/hle/service/nfc/mifare_user.cpp new file mode 100644 index 000000000..51523a3ae --- /dev/null +++ b/src/core/hle/service/nfc/mifare_user.cpp | |||
| @@ -0,0 +1,400 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/logging/log.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hid/hid_types.h" | ||
| 7 | #include "core/hle/ipc_helpers.h" | ||
| 8 | #include "core/hle/kernel/k_event.h" | ||
| 9 | #include "core/hle/service/nfc/mifare_user.h" | ||
| 10 | #include "core/hle/service/nfc/nfc_device.h" | ||
| 11 | #include "core/hle/service/nfc/nfc_result.h" | ||
| 12 | |||
| 13 | namespace Service::NFC { | ||
| 14 | |||
| 15 | MFIUser::MFIUser(Core::System& system_) | ||
| 16 | : ServiceFramework{system_, "NFC::MFIUser"}, service_context{system_, service_name} { | ||
| 17 | static const FunctionInfo functions[] = { | ||
| 18 | {0, &MFIUser::Initialize, "Initialize"}, | ||
| 19 | {1, &MFIUser::Finalize, "Finalize"}, | ||
| 20 | {2, &MFIUser::ListDevices, "ListDevices"}, | ||
| 21 | {3, &MFIUser::StartDetection, "StartDetection"}, | ||
| 22 | {4, &MFIUser::StopDetection, "StopDetection"}, | ||
| 23 | {5, &MFIUser::Read, "Read"}, | ||
| 24 | {6, &MFIUser::Write, "Write"}, | ||
| 25 | {7, &MFIUser::GetTagInfo, "GetTagInfo"}, | ||
| 26 | {8, &MFIUser::GetActivateEventHandle, "GetActivateEventHandle"}, | ||
| 27 | {9, &MFIUser::GetDeactivateEventHandle, "GetDeactivateEventHandle"}, | ||
| 28 | {10, &MFIUser::GetState, "GetState"}, | ||
| 29 | {11, &MFIUser::GetDeviceState, "GetDeviceState"}, | ||
| 30 | {12, &MFIUser::GetNpadId, "GetNpadId"}, | ||
| 31 | {13, &MFIUser::GetAvailabilityChangeEventHandle, "GetAvailabilityChangeEventHandle"}, | ||
| 32 | }; | ||
| 33 | RegisterHandlers(functions); | ||
| 34 | |||
| 35 | availability_change_event = service_context.CreateEvent("MFIUser:AvailabilityChangeEvent"); | ||
| 36 | |||
| 37 | for (u32 device_index = 0; device_index < 10; device_index++) { | ||
| 38 | devices[device_index] = | ||
| 39 | std::make_shared<NfcDevice>(Core::HID::IndexToNpadIdType(device_index), system, | ||
| 40 | service_context, availability_change_event); | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | MFIUser ::~MFIUser() { | ||
| 45 | availability_change_event->Close(); | ||
| 46 | } | ||
| 47 | |||
| 48 | void MFIUser::Initialize(Kernel::HLERequestContext& ctx) { | ||
| 49 | LOG_INFO(Service_NFC, "called"); | ||
| 50 | |||
| 51 | state = State::Initialized; | ||
| 52 | |||
| 53 | for (auto& device : devices) { | ||
| 54 | device->Initialize(); | ||
| 55 | } | ||
| 56 | |||
| 57 | IPC::ResponseBuilder rb{ctx, 2, 0}; | ||
| 58 | rb.Push(ResultSuccess); | ||
| 59 | } | ||
| 60 | |||
| 61 | void MFIUser::Finalize(Kernel::HLERequestContext& ctx) { | ||
| 62 | LOG_INFO(Service_NFC, "called"); | ||
| 63 | |||
| 64 | state = State::NonInitialized; | ||
| 65 | |||
| 66 | for (auto& device : devices) { | ||
| 67 | device->Finalize(); | ||
| 68 | } | ||
| 69 | |||
| 70 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 71 | rb.Push(ResultSuccess); | ||
| 72 | } | ||
| 73 | |||
| 74 | void MFIUser::ListDevices(Kernel::HLERequestContext& ctx) { | ||
| 75 | LOG_DEBUG(Service_NFC, "called"); | ||
| 76 | |||
| 77 | if (state == State::NonInitialized) { | ||
| 78 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 79 | rb.Push(MifareNfcDisabled); | ||
| 80 | return; | ||
| 81 | } | ||
| 82 | |||
| 83 | if (!ctx.CanWriteBuffer()) { | ||
| 84 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 85 | rb.Push(MifareInvalidArgument); | ||
| 86 | return; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (ctx.GetWriteBufferSize() == 0) { | ||
| 90 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 91 | rb.Push(MifareInvalidArgument); | ||
| 92 | return; | ||
| 93 | } | ||
| 94 | |||
| 95 | std::vector<u64> nfp_devices; | ||
| 96 | const std::size_t max_allowed_devices = ctx.GetWriteBufferNumElements<u64>(); | ||
| 97 | |||
| 98 | for (const auto& device : devices) { | ||
| 99 | if (nfp_devices.size() >= max_allowed_devices) { | ||
| 100 | continue; | ||
| 101 | } | ||
| 102 | if (device->GetCurrentState() != NFP::DeviceState::Unavailable) { | ||
| 103 | nfp_devices.push_back(device->GetHandle()); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | if (nfp_devices.empty()) { | ||
| 108 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 109 | rb.Push(MifareDeviceNotFound); | ||
| 110 | return; | ||
| 111 | } | ||
| 112 | |||
| 113 | ctx.WriteBuffer(nfp_devices); | ||
| 114 | |||
| 115 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 116 | rb.Push(ResultSuccess); | ||
| 117 | rb.Push(static_cast<s32>(nfp_devices.size())); | ||
| 118 | } | ||
| 119 | |||
| 120 | void MFIUser::StartDetection(Kernel::HLERequestContext& ctx) { | ||
| 121 | IPC::RequestParser rp{ctx}; | ||
| 122 | const auto device_handle{rp.Pop<u64>()}; | ||
| 123 | LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); | ||
| 124 | |||
| 125 | if (state == State::NonInitialized) { | ||
| 126 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 127 | rb.Push(MifareNfcDisabled); | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 131 | auto device = GetNfcDevice(device_handle); | ||
| 132 | |||
| 133 | if (!device.has_value()) { | ||
| 134 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 135 | rb.Push(MifareDeviceNotFound); | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | |||
| 139 | const auto result = device.value()->StartDetection(NFP::TagProtocol::All); | ||
| 140 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 141 | rb.Push(result); | ||
| 142 | } | ||
| 143 | |||
| 144 | void MFIUser::StopDetection(Kernel::HLERequestContext& ctx) { | ||
| 145 | IPC::RequestParser rp{ctx}; | ||
| 146 | const auto device_handle{rp.Pop<u64>()}; | ||
| 147 | LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); | ||
| 148 | |||
| 149 | if (state == State::NonInitialized) { | ||
| 150 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 151 | rb.Push(MifareNfcDisabled); | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | |||
| 155 | auto device = GetNfcDevice(device_handle); | ||
| 156 | |||
| 157 | if (!device.has_value()) { | ||
| 158 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 159 | rb.Push(MifareDeviceNotFound); | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | |||
| 163 | const auto result = device.value()->StopDetection(); | ||
| 164 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 165 | rb.Push(result); | ||
| 166 | } | ||
| 167 | |||
| 168 | void MFIUser::Read(Kernel::HLERequestContext& ctx) { | ||
| 169 | IPC::RequestParser rp{ctx}; | ||
| 170 | const auto device_handle{rp.Pop<u64>()}; | ||
| 171 | const auto buffer{ctx.ReadBuffer()}; | ||
| 172 | const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareReadBlockParameter>()}; | ||
| 173 | std::vector<NFP::MifareReadBlockParameter> read_commands(number_of_commands); | ||
| 174 | |||
| 175 | memcpy(read_commands.data(), buffer.data(), | ||
| 176 | number_of_commands * sizeof(NFP::MifareReadBlockParameter)); | ||
| 177 | |||
| 178 | LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, read_commands_size={}", | ||
| 179 | device_handle, number_of_commands); | ||
| 180 | |||
| 181 | if (state == State::NonInitialized) { | ||
| 182 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 183 | rb.Push(MifareNfcDisabled); | ||
| 184 | return; | ||
| 185 | } | ||
| 186 | |||
| 187 | auto device = GetNfcDevice(device_handle); | ||
| 188 | |||
| 189 | if (!device.has_value()) { | ||
| 190 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 191 | rb.Push(MifareDeviceNotFound); | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | |||
| 195 | Result result = ResultSuccess; | ||
| 196 | std::vector<NFP::MifareReadBlockData> out_data(number_of_commands); | ||
| 197 | for (std::size_t i = 0; i < number_of_commands; i++) { | ||
| 198 | result = device.value()->MifareRead(read_commands[i], out_data[i]); | ||
| 199 | if (result.IsError()) { | ||
| 200 | break; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | ctx.WriteBuffer(out_data); | ||
| 205 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 206 | rb.Push(result); | ||
| 207 | } | ||
| 208 | |||
| 209 | void MFIUser::Write(Kernel::HLERequestContext& ctx) { | ||
| 210 | IPC::RequestParser rp{ctx}; | ||
| 211 | const auto device_handle{rp.Pop<u64>()}; | ||
| 212 | const auto buffer{ctx.ReadBuffer()}; | ||
| 213 | const auto number_of_commands{ctx.GetReadBufferNumElements<NFP::MifareWriteBlockParameter>()}; | ||
| 214 | std::vector<NFP::MifareWriteBlockParameter> write_commands(number_of_commands); | ||
| 215 | |||
| 216 | memcpy(write_commands.data(), buffer.data(), | ||
| 217 | number_of_commands * sizeof(NFP::MifareWriteBlockParameter)); | ||
| 218 | |||
| 219 | LOG_INFO(Service_NFC, "(STUBBED) called, device_handle={}, write_commands_size={}", | ||
| 220 | device_handle, number_of_commands); | ||
| 221 | |||
| 222 | if (state == State::NonInitialized) { | ||
| 223 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 224 | rb.Push(MifareNfcDisabled); | ||
| 225 | return; | ||
| 226 | } | ||
| 227 | |||
| 228 | auto device = GetNfcDevice(device_handle); | ||
| 229 | |||
| 230 | if (!device.has_value()) { | ||
| 231 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 232 | rb.Push(MifareDeviceNotFound); | ||
| 233 | return; | ||
| 234 | } | ||
| 235 | |||
| 236 | Result result = ResultSuccess; | ||
| 237 | std::vector<NFP::MifareReadBlockData> out_data(number_of_commands); | ||
| 238 | for (std::size_t i = 0; i < number_of_commands; i++) { | ||
| 239 | result = device.value()->MifareWrite(write_commands[i]); | ||
| 240 | if (result.IsError()) { | ||
| 241 | break; | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | if (result.IsSuccess()) { | ||
| 246 | result = device.value()->Flush(); | ||
| 247 | } | ||
| 248 | |||
| 249 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 250 | rb.Push(result); | ||
| 251 | } | ||
| 252 | |||
| 253 | void MFIUser::GetTagInfo(Kernel::HLERequestContext& ctx) { | ||
| 254 | IPC::RequestParser rp{ctx}; | ||
| 255 | const auto device_handle{rp.Pop<u64>()}; | ||
| 256 | LOG_INFO(Service_NFC, "called, device_handle={}", device_handle); | ||
| 257 | |||
| 258 | if (state == State::NonInitialized) { | ||
| 259 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 260 | rb.Push(MifareNfcDisabled); | ||
| 261 | return; | ||
| 262 | } | ||
| 263 | |||
| 264 | auto device = GetNfcDevice(device_handle); | ||
| 265 | |||
| 266 | if (!device.has_value()) { | ||
| 267 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 268 | rb.Push(MifareDeviceNotFound); | ||
| 269 | return; | ||
| 270 | } | ||
| 271 | |||
| 272 | NFP::TagInfo tag_info{}; | ||
| 273 | const auto result = device.value()->GetTagInfo(tag_info, true); | ||
| 274 | ctx.WriteBuffer(tag_info); | ||
| 275 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 276 | rb.Push(result); | ||
| 277 | } | ||
| 278 | |||
| 279 | void MFIUser::GetActivateEventHandle(Kernel::HLERequestContext& ctx) { | ||
| 280 | IPC::RequestParser rp{ctx}; | ||
| 281 | const auto device_handle{rp.Pop<u64>()}; | ||
| 282 | LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); | ||
| 283 | |||
| 284 | if (state == State::NonInitialized) { | ||
| 285 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 286 | rb.Push(MifareNfcDisabled); | ||
| 287 | return; | ||
| 288 | } | ||
| 289 | |||
| 290 | auto device = GetNfcDevice(device_handle); | ||
| 291 | |||
| 292 | if (!device.has_value()) { | ||
| 293 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 294 | rb.Push(MifareDeviceNotFound); | ||
| 295 | return; | ||
| 296 | } | ||
| 297 | |||
| 298 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 299 | rb.Push(ResultSuccess); | ||
| 300 | rb.PushCopyObjects(device.value()->GetActivateEvent()); | ||
| 301 | } | ||
| 302 | |||
| 303 | void MFIUser::GetDeactivateEventHandle(Kernel::HLERequestContext& ctx) { | ||
| 304 | IPC::RequestParser rp{ctx}; | ||
| 305 | const auto device_handle{rp.Pop<u64>()}; | ||
| 306 | LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); | ||
| 307 | |||
| 308 | if (state == State::NonInitialized) { | ||
| 309 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 310 | rb.Push(MifareNfcDisabled); | ||
| 311 | return; | ||
| 312 | } | ||
| 313 | |||
| 314 | auto device = GetNfcDevice(device_handle); | ||
| 315 | |||
| 316 | if (!device.has_value()) { | ||
| 317 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 318 | rb.Push(MifareDeviceNotFound); | ||
| 319 | return; | ||
| 320 | } | ||
| 321 | |||
| 322 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 323 | rb.Push(ResultSuccess); | ||
| 324 | rb.PushCopyObjects(device.value()->GetDeactivateEvent()); | ||
| 325 | } | ||
| 326 | |||
| 327 | void MFIUser::GetState(Kernel::HLERequestContext& ctx) { | ||
| 328 | LOG_DEBUG(Service_NFC, "called"); | ||
| 329 | |||
| 330 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 331 | rb.Push(ResultSuccess); | ||
| 332 | rb.PushEnum(state); | ||
| 333 | } | ||
| 334 | |||
| 335 | void MFIUser::GetDeviceState(Kernel::HLERequestContext& ctx) { | ||
| 336 | IPC::RequestParser rp{ctx}; | ||
| 337 | const auto device_handle{rp.Pop<u64>()}; | ||
| 338 | LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); | ||
| 339 | |||
| 340 | auto device = GetNfcDevice(device_handle); | ||
| 341 | |||
| 342 | if (!device.has_value()) { | ||
| 343 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 344 | rb.Push(MifareDeviceNotFound); | ||
| 345 | return; | ||
| 346 | } | ||
| 347 | |||
| 348 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 349 | rb.Push(ResultSuccess); | ||
| 350 | rb.PushEnum(device.value()->GetCurrentState()); | ||
| 351 | } | ||
| 352 | |||
| 353 | void MFIUser::GetNpadId(Kernel::HLERequestContext& ctx) { | ||
| 354 | IPC::RequestParser rp{ctx}; | ||
| 355 | const auto device_handle{rp.Pop<u64>()}; | ||
| 356 | LOG_DEBUG(Service_NFC, "called, device_handle={}", device_handle); | ||
| 357 | |||
| 358 | if (state == State::NonInitialized) { | ||
| 359 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 360 | rb.Push(MifareNfcDisabled); | ||
| 361 | return; | ||
| 362 | } | ||
| 363 | |||
| 364 | auto device = GetNfcDevice(device_handle); | ||
| 365 | |||
| 366 | if (!device.has_value()) { | ||
| 367 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 368 | rb.Push(MifareDeviceNotFound); | ||
| 369 | return; | ||
| 370 | } | ||
| 371 | |||
| 372 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 373 | rb.Push(ResultSuccess); | ||
| 374 | rb.PushEnum(device.value()->GetNpadId()); | ||
| 375 | } | ||
| 376 | |||
| 377 | void MFIUser::GetAvailabilityChangeEventHandle(Kernel::HLERequestContext& ctx) { | ||
| 378 | LOG_INFO(Service_NFC, "called"); | ||
| 379 | |||
| 380 | if (state == State::NonInitialized) { | ||
| 381 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 382 | rb.Push(MifareNfcDisabled); | ||
| 383 | return; | ||
| 384 | } | ||
| 385 | |||
| 386 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 387 | rb.Push(ResultSuccess); | ||
| 388 | rb.PushCopyObjects(availability_change_event->GetReadableEvent()); | ||
| 389 | } | ||
| 390 | |||
| 391 | std::optional<std::shared_ptr<NfcDevice>> MFIUser::GetNfcDevice(u64 handle) { | ||
| 392 | for (auto& device : devices) { | ||
| 393 | if (device->GetHandle() == handle) { | ||
| 394 | return device; | ||
| 395 | } | ||
| 396 | } | ||
| 397 | return std::nullopt; | ||
| 398 | } | ||
| 399 | |||
| 400 | } // namespace Service::NFC | ||
diff --git a/src/core/hle/service/nfc/mifare_user.h b/src/core/hle/service/nfc/mifare_user.h new file mode 100644 index 000000000..0e0638cb6 --- /dev/null +++ b/src/core/hle/service/nfc/mifare_user.h | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <array> | ||
| 7 | #include <memory> | ||
| 8 | #include <optional> | ||
| 9 | |||
| 10 | #include "core/hle/service/kernel_helpers.h" | ||
| 11 | #include "core/hle/service/service.h" | ||
| 12 | |||
| 13 | namespace Service::NFC { | ||
| 14 | class NfcDevice; | ||
| 15 | |||
| 16 | class MFIUser final : public ServiceFramework<MFIUser> { | ||
| 17 | public: | ||
| 18 | explicit MFIUser(Core::System& system_); | ||
| 19 | ~MFIUser(); | ||
| 20 | |||
| 21 | private: | ||
| 22 | enum class State : u32 { | ||
| 23 | NonInitialized, | ||
| 24 | Initialized, | ||
| 25 | }; | ||
| 26 | |||
| 27 | void Initialize(Kernel::HLERequestContext& ctx); | ||
| 28 | void Finalize(Kernel::HLERequestContext& ctx); | ||
| 29 | void ListDevices(Kernel::HLERequestContext& ctx); | ||
| 30 | void StartDetection(Kernel::HLERequestContext& ctx); | ||
| 31 | void StopDetection(Kernel::HLERequestContext& ctx); | ||
| 32 | void Read(Kernel::HLERequestContext& ctx); | ||
| 33 | void Write(Kernel::HLERequestContext& ctx); | ||
| 34 | void GetTagInfo(Kernel::HLERequestContext& ctx); | ||
| 35 | void GetActivateEventHandle(Kernel::HLERequestContext& ctx); | ||
| 36 | void GetDeactivateEventHandle(Kernel::HLERequestContext& ctx); | ||
| 37 | void GetState(Kernel::HLERequestContext& ctx); | ||
| 38 | void GetDeviceState(Kernel::HLERequestContext& ctx); | ||
| 39 | void GetNpadId(Kernel::HLERequestContext& ctx); | ||
| 40 | void GetAvailabilityChangeEventHandle(Kernel::HLERequestContext& ctx); | ||
| 41 | |||
| 42 | std::optional<std::shared_ptr<NfcDevice>> GetNfcDevice(u64 handle); | ||
| 43 | |||
| 44 | KernelHelpers::ServiceContext service_context; | ||
| 45 | |||
| 46 | std::array<std::shared_ptr<NfcDevice>, 10> devices{}; | ||
| 47 | |||
| 48 | State state{State::NonInitialized}; | ||
| 49 | Kernel::KEvent* availability_change_event; | ||
| 50 | }; | ||
| 51 | |||
| 52 | } // namespace Service::NFC | ||
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp index 2f4bacb3b..b17b18ab9 100644 --- a/src/core/hle/service/nfc/nfc.cpp +++ b/src/core/hle/service/nfc/nfc.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/service/nfc/mifare_user.h" | ||
| 9 | #include "core/hle/service/nfc/nfc.h" | 10 | #include "core/hle/service/nfc/nfc.h" |
| 10 | #include "core/hle/service/nfc/nfc_user.h" | 11 | #include "core/hle/service/nfc/nfc_user.h" |
| 11 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| @@ -50,32 +51,6 @@ private: | |||
| 50 | } | 51 | } |
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | class MFIUser final : public ServiceFramework<MFIUser> { | ||
| 54 | public: | ||
| 55 | explicit MFIUser(Core::System& system_) : ServiceFramework{system_, "NFC::MFIUser"} { | ||
| 56 | // clang-format off | ||
| 57 | static const FunctionInfo functions[] = { | ||
| 58 | {0, nullptr, "Initialize"}, | ||
| 59 | {1, nullptr, "Finalize"}, | ||
| 60 | {2, nullptr, "ListDevices"}, | ||
| 61 | {3, nullptr, "StartDetection"}, | ||
| 62 | {4, nullptr, "StopDetection"}, | ||
| 63 | {5, nullptr, "Read"}, | ||
| 64 | {6, nullptr, "Write"}, | ||
| 65 | {7, nullptr, "GetTagInfo"}, | ||
| 66 | {8, nullptr, "GetActivateEventHandle"}, | ||
| 67 | {9, nullptr, "GetDeactivateEventHandle"}, | ||
| 68 | {10, nullptr, "GetState"}, | ||
| 69 | {11, nullptr, "GetDeviceState"}, | ||
| 70 | {12, nullptr, "GetNpadId"}, | ||
| 71 | {13, nullptr, "GetAvailabilityChangeEventHandle"}, | ||
| 72 | }; | ||
| 73 | // clang-format on | ||
| 74 | |||
| 75 | RegisterHandlers(functions); | ||
| 76 | } | ||
| 77 | }; | ||
| 78 | |||
| 79 | class NFC_MF_U final : public ServiceFramework<NFC_MF_U> { | 54 | class NFC_MF_U final : public ServiceFramework<NFC_MF_U> { |
| 80 | public: | 55 | public: |
| 81 | explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} { | 56 | explicit NFC_MF_U(Core::System& system_) : ServiceFramework{system_, "nfc:mf:u"} { |
diff --git a/src/core/hle/service/nfc/nfc_device.cpp b/src/core/hle/service/nfc/nfc_device.cpp index 4d514cf5f..78578f723 100644 --- a/src/core/hle/service/nfc/nfc_device.cpp +++ b/src/core/hle/service/nfc/nfc_device.cpp | |||
| @@ -77,11 +77,13 @@ bool NfcDevice::LoadNfcTag(std::span<const u8> data) { | |||
| 77 | return false; | 77 | return false; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | if (data.size() != sizeof(NFP::EncryptedNTAG215File)) { | 80 | if (data.size() < sizeof(NFP::EncryptedNTAG215File)) { |
| 81 | LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); | 81 | LOG_ERROR(Service_NFC, "Not an amiibo, size={}", data.size()); |
| 82 | return false; | 82 | return false; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | tag_data.resize(data.size()); | ||
| 86 | memcpy(tag_data.data(), data.data(), data.size()); | ||
| 85 | memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); | 87 | memcpy(&encrypted_tag_data, data.data(), sizeof(NFP::EncryptedNTAG215File)); |
| 86 | 88 | ||
| 87 | device_state = NFP::DeviceState::TagFound; | 89 | device_state = NFP::DeviceState::TagFound; |
| @@ -121,7 +123,7 @@ void NfcDevice::Finalize() { | |||
| 121 | device_state = NFP::DeviceState::Unavailable; | 123 | device_state = NFP::DeviceState::Unavailable; |
| 122 | } | 124 | } |
| 123 | 125 | ||
| 124 | Result NfcDevice::StartDetection(s32 protocol_) { | 126 | Result NfcDevice::StartDetection(NFP::TagProtocol allowed_protocol) { |
| 125 | if (device_state != NFP::DeviceState::Initialized && | 127 | if (device_state != NFP::DeviceState::Initialized && |
| 126 | device_state != NFP::DeviceState::TagRemoved) { | 128 | device_state != NFP::DeviceState::TagRemoved) { |
| 127 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | 129 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); |
| @@ -134,7 +136,7 @@ Result NfcDevice::StartDetection(s32 protocol_) { | |||
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | device_state = NFP::DeviceState::SearchingForTag; | 138 | device_state = NFP::DeviceState::SearchingForTag; |
| 137 | protocol = protocol_; | 139 | allowed_protocols = allowed_protocol; |
| 138 | return ResultSuccess; | 140 | return ResultSuccess; |
| 139 | } | 141 | } |
| 140 | 142 | ||
| @@ -160,7 +162,7 @@ Result NfcDevice::StopDetection() { | |||
| 160 | return WrongDeviceState; | 162 | return WrongDeviceState; |
| 161 | } | 163 | } |
| 162 | 164 | ||
| 163 | Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const { | 165 | Result NfcDevice::Flush() { |
| 164 | if (device_state != NFP::DeviceState::TagFound && | 166 | if (device_state != NFP::DeviceState::TagFound && |
| 165 | device_state != NFP::DeviceState::TagMounted) { | 167 | device_state != NFP::DeviceState::TagMounted) { |
| 166 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | 168 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); |
| @@ -170,6 +172,34 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const { | |||
| 170 | return WrongDeviceState; | 172 | return WrongDeviceState; |
| 171 | } | 173 | } |
| 172 | 174 | ||
| 175 | if (!npad_device->WriteNfc(tag_data)) { | ||
| 176 | LOG_ERROR(Service_NFP, "Error writing to file"); | ||
| 177 | return MifareReadError; | ||
| 178 | } | ||
| 179 | |||
| 180 | return ResultSuccess; | ||
| 181 | } | ||
| 182 | |||
| 183 | Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const { | ||
| 184 | if (device_state != NFP::DeviceState::TagFound && | ||
| 185 | device_state != NFP::DeviceState::TagMounted) { | ||
| 186 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | ||
| 187 | if (device_state == NFP::DeviceState::TagRemoved) { | ||
| 188 | return TagRemoved; | ||
| 189 | } | ||
| 190 | return WrongDeviceState; | ||
| 191 | } | ||
| 192 | |||
| 193 | if (is_mifare) { | ||
| 194 | tag_info = { | ||
| 195 | .uuid = encrypted_tag_data.uuid.uid, | ||
| 196 | .uuid_length = static_cast<u8>(encrypted_tag_data.uuid.uid.size()), | ||
| 197 | .protocol = NFP::TagProtocol::TypeA, | ||
| 198 | .tag_type = NFP::TagType::Type4, | ||
| 199 | }; | ||
| 200 | return ResultSuccess; | ||
| 201 | } | ||
| 202 | |||
| 173 | // Protocol and tag type may change here | 203 | // Protocol and tag type may change here |
| 174 | tag_info = { | 204 | tag_info = { |
| 175 | .uuid = encrypted_tag_data.uuid.uid, | 205 | .uuid = encrypted_tag_data.uuid.uid, |
| @@ -181,6 +211,52 @@ Result NfcDevice::GetTagInfo(NFP::TagInfo& tag_info) const { | |||
| 181 | return ResultSuccess; | 211 | return ResultSuccess; |
| 182 | } | 212 | } |
| 183 | 213 | ||
| 214 | Result NfcDevice::MifareRead(const NFP::MifareReadBlockParameter& parameter, | ||
| 215 | NFP::MifareReadBlockData& read_block_data) { | ||
| 216 | const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock); | ||
| 217 | read_block_data.sector_number = parameter.sector_number; | ||
| 218 | |||
| 219 | if (device_state != NFP::DeviceState::TagFound && | ||
| 220 | device_state != NFP::DeviceState::TagMounted) { | ||
| 221 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | ||
| 222 | if (device_state == NFP::DeviceState::TagRemoved) { | ||
| 223 | return TagRemoved; | ||
| 224 | } | ||
| 225 | return WrongDeviceState; | ||
| 226 | } | ||
| 227 | |||
| 228 | if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) { | ||
| 229 | return MifareReadError; | ||
| 230 | } | ||
| 231 | |||
| 232 | // TODO: Use parameter.sector_key to read encrypted data | ||
| 233 | memcpy(read_block_data.data.data(), tag_data.data() + sector_index, sizeof(NFP::DataBlock)); | ||
| 234 | |||
| 235 | return ResultSuccess; | ||
| 236 | } | ||
| 237 | |||
| 238 | Result NfcDevice::MifareWrite(const NFP::MifareWriteBlockParameter& parameter) { | ||
| 239 | const std::size_t sector_index = parameter.sector_number * sizeof(NFP::DataBlock); | ||
| 240 | |||
| 241 | if (device_state != NFP::DeviceState::TagFound && | ||
| 242 | device_state != NFP::DeviceState::TagMounted) { | ||
| 243 | LOG_ERROR(Service_NFC, "Wrong device state {}", device_state); | ||
| 244 | if (device_state == NFP::DeviceState::TagRemoved) { | ||
| 245 | return TagRemoved; | ||
| 246 | } | ||
| 247 | return WrongDeviceState; | ||
| 248 | } | ||
| 249 | |||
| 250 | if (tag_data.size() < sector_index + sizeof(NFP::DataBlock)) { | ||
| 251 | return MifareReadError; | ||
| 252 | } | ||
| 253 | |||
| 254 | // TODO: Use parameter.sector_key to encrypt the data | ||
| 255 | memcpy(tag_data.data() + sector_index, parameter.data.data(), sizeof(NFP::DataBlock)); | ||
| 256 | |||
| 257 | return ResultSuccess; | ||
| 258 | } | ||
| 259 | |||
| 184 | u64 NfcDevice::GetHandle() const { | 260 | u64 NfcDevice::GetHandle() const { |
| 185 | // Generate a handle based of the npad id | 261 | // Generate a handle based of the npad id |
| 186 | return static_cast<u64>(npad_id); | 262 | return static_cast<u64>(npad_id); |
diff --git a/src/core/hle/service/nfc/nfc_device.h b/src/core/hle/service/nfc/nfc_device.h index fa1348f1a..a6e114d36 100644 --- a/src/core/hle/service/nfc/nfc_device.h +++ b/src/core/hle/service/nfc/nfc_device.h | |||
| @@ -34,10 +34,16 @@ public: | |||
| 34 | void Initialize(); | 34 | void Initialize(); |
| 35 | void Finalize(); | 35 | void Finalize(); |
| 36 | 36 | ||
| 37 | Result StartDetection(s32 protocol_); | 37 | Result StartDetection(NFP::TagProtocol allowed_protocol); |
| 38 | Result StopDetection(); | 38 | Result StopDetection(); |
| 39 | Result Flush(); | ||
| 39 | 40 | ||
| 40 | Result GetTagInfo(NFP::TagInfo& tag_info) const; | 41 | Result GetTagInfo(NFP::TagInfo& tag_info, bool is_mifare) const; |
| 42 | |||
| 43 | Result MifareRead(const NFP::MifareReadBlockParameter& parameter, | ||
| 44 | NFP::MifareReadBlockData& read_block_data); | ||
| 45 | |||
| 46 | Result MifareWrite(const NFP::MifareWriteBlockParameter& parameter); | ||
| 41 | 47 | ||
| 42 | u64 GetHandle() const; | 48 | u64 GetHandle() const; |
| 43 | NFP::DeviceState GetCurrentState() const; | 49 | NFP::DeviceState GetCurrentState() const; |
| @@ -61,10 +67,11 @@ private: | |||
| 61 | Kernel::KEvent* deactivate_event = nullptr; | 67 | Kernel::KEvent* deactivate_event = nullptr; |
| 62 | Kernel::KEvent* availability_change_event = nullptr; | 68 | Kernel::KEvent* availability_change_event = nullptr; |
| 63 | 69 | ||
| 64 | s32 protocol{}; | 70 | NFP::TagProtocol allowed_protocols{}; |
| 65 | NFP::DeviceState device_state{NFP::DeviceState::Unavailable}; | 71 | NFP::DeviceState device_state{NFP::DeviceState::Unavailable}; |
| 66 | 72 | ||
| 67 | NFP::EncryptedNTAG215File encrypted_tag_data{}; | 73 | NFP::EncryptedNTAG215File encrypted_tag_data{}; |
| 74 | std::vector<u8> tag_data{}; | ||
| 68 | }; | 75 | }; |
| 69 | 76 | ||
| 70 | } // namespace Service::NFC | 77 | } // namespace Service::NFC |
diff --git a/src/core/hle/service/nfc/nfc_result.h b/src/core/hle/service/nfc/nfc_result.h index 537dc15f4..146b8ba61 100644 --- a/src/core/hle/service/nfc/nfc_result.h +++ b/src/core/hle/service/nfc/nfc_result.h | |||
| @@ -12,6 +12,12 @@ constexpr Result InvalidArgument(ErrorModule::NFC, 65); | |||
| 12 | constexpr Result WrongDeviceState(ErrorModule::NFC, 73); | 12 | constexpr Result WrongDeviceState(ErrorModule::NFC, 73); |
| 13 | constexpr Result NfcDisabled(ErrorModule::NFC, 80); | 13 | constexpr Result NfcDisabled(ErrorModule::NFC, 80); |
| 14 | constexpr Result TagRemoved(ErrorModule::NFC, 97); | 14 | constexpr Result TagRemoved(ErrorModule::NFC, 97); |
| 15 | constexpr Result CorruptedData(ErrorModule::NFC, 144); | 15 | |
| 16 | constexpr Result MifareDeviceNotFound(ErrorModule::NFCMifare, 64); | ||
| 17 | constexpr Result MifareInvalidArgument(ErrorModule::NFCMifare, 65); | ||
| 18 | constexpr Result MifareWrongDeviceState(ErrorModule::NFCMifare, 73); | ||
| 19 | constexpr Result MifareNfcDisabled(ErrorModule::NFCMifare, 80); | ||
| 20 | constexpr Result MifareTagRemoved(ErrorModule::NFCMifare, 97); | ||
| 21 | constexpr Result MifareReadError(ErrorModule::NFCMifare, 288); | ||
| 16 | 22 | ||
| 17 | } // namespace Service::NFC | 23 | } // namespace Service::NFC |
diff --git a/src/core/hle/service/nfc/nfc_user.cpp b/src/core/hle/service/nfc/nfc_user.cpp index ced2d560b..4615697e2 100644 --- a/src/core/hle/service/nfc/nfc_user.cpp +++ b/src/core/hle/service/nfc/nfc_user.cpp | |||
| @@ -201,7 +201,7 @@ void IUser::AttachAvailabilityChangeEvent(Kernel::HLERequestContext& ctx) { | |||
| 201 | void IUser::StartDetection(Kernel::HLERequestContext& ctx) { | 201 | void IUser::StartDetection(Kernel::HLERequestContext& ctx) { |
| 202 | IPC::RequestParser rp{ctx}; | 202 | IPC::RequestParser rp{ctx}; |
| 203 | const auto device_handle{rp.Pop<u64>()}; | 203 | const auto device_handle{rp.Pop<u64>()}; |
| 204 | const auto nfp_protocol{rp.Pop<s32>()}; | 204 | const auto nfp_protocol{rp.PopEnum<NFP::TagProtocol>()}; |
| 205 | LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); | 205 | LOG_INFO(Service_NFC, "called, device_handle={}, nfp_protocol={}", device_handle, nfp_protocol); |
| 206 | 206 | ||
| 207 | if (state == State::NonInitialized) { | 207 | if (state == State::NonInitialized) { |
| @@ -267,7 +267,7 @@ void IUser::GetTagInfo(Kernel::HLERequestContext& ctx) { | |||
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | NFP::TagInfo tag_info{}; | 269 | NFP::TagInfo tag_info{}; |
| 270 | const auto result = device.value()->GetTagInfo(tag_info); | 270 | const auto result = device.value()->GetTagInfo(tag_info, false); |
| 271 | ctx.WriteBuffer(tag_info); | 271 | ctx.WriteBuffer(tag_info); |
| 272 | IPC::ResponseBuilder rb{ctx, 2}; | 272 | IPC::ResponseBuilder rb{ctx, 2}; |
| 273 | rb.Push(result); | 273 | rb.Push(result); |
diff --git a/src/core/hle/service/nfp/nfp_types.h b/src/core/hle/service/nfp/nfp_types.h index 69858096a..fc228c2b2 100644 --- a/src/core/hle/service/nfp/nfp_types.h +++ b/src/core/hle/service/nfp/nfp_types.h | |||
| @@ -106,11 +106,24 @@ enum class CabinetMode : u8 { | |||
| 106 | StartFormatter, | 106 | StartFormatter, |
| 107 | }; | 107 | }; |
| 108 | 108 | ||
| 109 | enum class MifareCmd : u8 { | ||
| 110 | AuthA = 0x60, | ||
| 111 | AuthB = 0x61, | ||
| 112 | Read = 0x30, | ||
| 113 | Write = 0xA0, | ||
| 114 | Transfer = 0xB0, | ||
| 115 | Decrement = 0xC0, | ||
| 116 | Increment = 0xC1, | ||
| 117 | Store = 0xC2 | ||
| 118 | }; | ||
| 119 | |||
| 109 | using UniqueSerialNumber = std::array<u8, 7>; | 120 | using UniqueSerialNumber = std::array<u8, 7>; |
| 110 | using LockBytes = std::array<u8, 2>; | 121 | using LockBytes = std::array<u8, 2>; |
| 111 | using HashData = std::array<u8, 0x20>; | 122 | using HashData = std::array<u8, 0x20>; |
| 112 | using ApplicationArea = std::array<u8, 0xD8>; | 123 | using ApplicationArea = std::array<u8, 0xD8>; |
| 113 | using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; | 124 | using AmiiboName = std::array<char, (amiibo_name_length * 4) + 1>; |
| 125 | using DataBlock = std::array<u8, 0x10>; | ||
| 126 | using KeyData = std::array<u8, 0x6>; | ||
| 114 | 127 | ||
| 115 | struct TagUuid { | 128 | struct TagUuid { |
| 116 | UniqueSerialNumber uid; | 129 | UniqueSerialNumber uid; |
| @@ -323,4 +336,37 @@ struct RegisterInfo { | |||
| 323 | }; | 336 | }; |
| 324 | static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); | 337 | static_assert(sizeof(RegisterInfo) == 0x100, "RegisterInfo is an invalid size"); |
| 325 | 338 | ||
| 339 | struct SectorKey { | ||
| 340 | MifareCmd command; | ||
| 341 | u8 unknown; // Usually 1 | ||
| 342 | INSERT_PADDING_BYTES(0x6); | ||
| 343 | KeyData sector_key; | ||
| 344 | INSERT_PADDING_BYTES(0x2); | ||
| 345 | }; | ||
| 346 | static_assert(sizeof(SectorKey) == 0x10, "SectorKey is an invalid size"); | ||
| 347 | |||
| 348 | struct MifareReadBlockParameter { | ||
| 349 | u8 sector_number; | ||
| 350 | INSERT_PADDING_BYTES(0x7); | ||
| 351 | SectorKey sector_key; | ||
| 352 | }; | ||
| 353 | static_assert(sizeof(MifareReadBlockParameter) == 0x18, | ||
| 354 | "MifareReadBlockParameter is an invalid size"); | ||
| 355 | |||
| 356 | struct MifareReadBlockData { | ||
| 357 | DataBlock data; | ||
| 358 | u8 sector_number; | ||
| 359 | INSERT_PADDING_BYTES(0x7); | ||
| 360 | }; | ||
| 361 | static_assert(sizeof(MifareReadBlockData) == 0x18, "MifareReadBlockData is an invalid size"); | ||
| 362 | |||
| 363 | struct MifareWriteBlockParameter { | ||
| 364 | DataBlock data; | ||
| 365 | u8 sector_number; | ||
| 366 | INSERT_PADDING_BYTES(0x7); | ||
| 367 | SectorKey sector_key; | ||
| 368 | }; | ||
| 369 | static_assert(sizeof(MifareWriteBlockParameter) == 0x28, | ||
| 370 | "MifareWriteBlockParameter is an invalid size"); | ||
| 371 | |||
| 326 | } // namespace Service::NFP | 372 | } // namespace Service::NFP |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index e3ef06481..4fa9f51a6 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -129,6 +129,9 @@ static_assert(sizeof(NifmNetworkProfileData) == 0x18E, | |||
| 129 | "NifmNetworkProfileData has incorrect size."); | 129 | "NifmNetworkProfileData has incorrect size."); |
| 130 | #pragma pack(pop) | 130 | #pragma pack(pop) |
| 131 | 131 | ||
| 132 | constexpr Result ResultPendingConnection{ErrorModule::NIFM, 111}; | ||
| 133 | constexpr Result ResultNetworkCommunicationDisabled{ErrorModule::NIFM, 1111}; | ||
| 134 | |||
| 132 | class IScanRequest final : public ServiceFramework<IScanRequest> { | 135 | class IScanRequest final : public ServiceFramework<IScanRequest> { |
| 133 | public: | 136 | public: |
| 134 | explicit IScanRequest(Core::System& system_) : ServiceFramework{system_, "IScanRequest"} { | 137 | explicit IScanRequest(Core::System& system_) : ServiceFramework{system_, "IScanRequest"} { |
| @@ -192,6 +195,10 @@ private: | |||
| 192 | void Submit(Kernel::HLERequestContext& ctx) { | 195 | void Submit(Kernel::HLERequestContext& ctx) { |
| 193 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 196 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 194 | 197 | ||
| 198 | if (state == RequestState::NotSubmitted) { | ||
| 199 | UpdateState(RequestState::Pending); | ||
| 200 | } | ||
| 201 | |||
| 195 | IPC::ResponseBuilder rb{ctx, 2}; | 202 | IPC::ResponseBuilder rb{ctx, 2}; |
| 196 | rb.Push(ResultSuccess); | 203 | rb.Push(ResultSuccess); |
| 197 | } | 204 | } |
| @@ -201,19 +208,32 @@ private: | |||
| 201 | 208 | ||
| 202 | IPC::ResponseBuilder rb{ctx, 3}; | 209 | IPC::ResponseBuilder rb{ctx, 3}; |
| 203 | rb.Push(ResultSuccess); | 210 | rb.Push(ResultSuccess); |
| 204 | 211 | rb.PushEnum(state); | |
| 205 | if (Network::GetHostIPv4Address().has_value()) { | ||
| 206 | rb.PushEnum(RequestState::Connected); | ||
| 207 | } else { | ||
| 208 | rb.PushEnum(RequestState::NotSubmitted); | ||
| 209 | } | ||
| 210 | } | 212 | } |
| 211 | 213 | ||
| 212 | void GetResult(Kernel::HLERequestContext& ctx) { | 214 | void GetResult(Kernel::HLERequestContext& ctx) { |
| 213 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); | 215 | LOG_WARNING(Service_NIFM, "(STUBBED) called"); |
| 214 | 216 | ||
| 217 | const auto result = [this] { | ||
| 218 | const auto has_connection = Network::GetHostIPv4Address().has_value(); | ||
| 219 | switch (state) { | ||
| 220 | case RequestState::NotSubmitted: | ||
| 221 | return has_connection ? ResultSuccess : ResultNetworkCommunicationDisabled; | ||
| 222 | case RequestState::Pending: | ||
| 223 | if (has_connection) { | ||
| 224 | UpdateState(RequestState::Connected); | ||
| 225 | } else { | ||
| 226 | UpdateState(RequestState::Error); | ||
| 227 | } | ||
| 228 | return ResultPendingConnection; | ||
| 229 | case RequestState::Connected: | ||
| 230 | default: | ||
| 231 | return ResultSuccess; | ||
| 232 | } | ||
| 233 | }(); | ||
| 234 | |||
| 215 | IPC::ResponseBuilder rb{ctx, 2}; | 235 | IPC::ResponseBuilder rb{ctx, 2}; |
| 216 | rb.Push(ResultSuccess); | 236 | rb.Push(result); |
| 217 | } | 237 | } |
| 218 | 238 | ||
| 219 | void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { | 239 | void GetSystemEventReadableHandles(Kernel::HLERequestContext& ctx) { |
| @@ -252,8 +272,15 @@ private: | |||
| 252 | rb.Push<u32>(0); | 272 | rb.Push<u32>(0); |
| 253 | } | 273 | } |
| 254 | 274 | ||
| 275 | void UpdateState(RequestState new_state) { | ||
| 276 | state = new_state; | ||
| 277 | event1->Signal(); | ||
| 278 | } | ||
| 279 | |||
| 255 | KernelHelpers::ServiceContext service_context; | 280 | KernelHelpers::ServiceContext service_context; |
| 256 | 281 | ||
| 282 | RequestState state; | ||
| 283 | |||
| 257 | Kernel::KEvent* event1; | 284 | Kernel::KEvent* event1; |
| 258 | Kernel::KEvent* event2; | 285 | Kernel::KEvent* event2; |
| 259 | }; | 286 | }; |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 460bef976..9b22397db 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <vector> | 11 | #include <vector> |
| 12 | 12 | ||
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/polyfill_thread.h" | ||
| 14 | #include "core/hle/result.h" | 15 | #include "core/hle/result.h" |
| 15 | #include "core/hle/service/kernel_helpers.h" | 16 | #include "core/hle/service/kernel_helpers.h" |
| 16 | 17 | ||
diff --git a/src/core/internal_network/network_interface.cpp b/src/core/internal_network/network_interface.cpp index 057fd3661..7b8e510a2 100644 --- a/src/core/internal_network/network_interface.cpp +++ b/src/core/internal_network/network_interface.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/bit_cast.h" | 9 | #include "common/bit_cast.h" |
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/polyfill_ranges.h" | ||
| 12 | #include "common/settings.h" | 13 | #include "common/settings.h" |
| 13 | #include "common/string_util.h" | 14 | #include "common/string_util.h" |
| 14 | #include "core/internal_network/network_interface.h" | 15 | #include "core/internal_network/network_interface.h" |
diff --git a/src/core/precompiled_headers.h b/src/core/precompiled_headers.h new file mode 100644 index 000000000..30a31001d --- /dev/null +++ b/src/core/precompiled_headers.h | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <boost/container/flat_map.hpp> // used by service.h which is heavily included | ||
| 7 | #include <boost/intrusive/rbtree.hpp> // used by k_auto_object.h which is heavily included | ||
| 8 | |||
| 9 | #include "common/common_precompiled_headers.h" | ||
| 10 | |||
| 11 | #include "core/hle/kernel/k_process.h" | ||
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 6e21296f6..77821e047 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -38,7 +38,7 @@ std::string GetTimestamp() { | |||
| 38 | 38 | ||
| 39 | using namespace nlohmann; | 39 | using namespace nlohmann; |
| 40 | 40 | ||
| 41 | void SaveToFile(json json, const std::filesystem::path& filename) { | 41 | void SaveToFile(const json& json, const std::filesystem::path& filename) { |
| 42 | if (!Common::FS::CreateParentDirs(filename)) { | 42 | if (!Common::FS::CreateParentDirs(filename)) { |
| 43 | LOG_ERROR(Core, "Failed to create path for '{}' to save report!", | 43 | LOG_ERROR(Core, "Failed to create path for '{}' to save report!", |
| 44 | Common::FS::PathToUTF8String(filename)); | 44 | Common::FS::PathToUTF8String(filename)); |
| @@ -81,8 +81,8 @@ json GetReportCommonData(u64 title_id, Result result, const std::string& timesta | |||
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 sp, u64 pc, | 83 | json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 sp, u64 pc, |
| 84 | u64 pstate, std::array<u64, 31> registers, | 84 | u64 pstate, const std::array<u64, 31>& registers, |
| 85 | std::optional<std::array<u64, 32>> backtrace = {}) { | 85 | const std::optional<std::array<u64, 32>>& backtrace = {}) { |
| 86 | auto out = json{ | 86 | auto out = json{ |
| 87 | {"entry_point", fmt::format("{:016X}", entry_point)}, | 87 | {"entry_point", fmt::format("{:016X}", entry_point)}, |
| 88 | {"sp", fmt::format("{:016X}", sp)}, | 88 | {"sp", fmt::format("{:016X}", sp)}, |
| @@ -224,11 +224,11 @@ void Reporter::SaveCrashReport(u64 title_id, Result result, u64 set_flags, u64 e | |||
| 224 | 224 | ||
| 225 | out["processor_state"] = std::move(proc_out); | 225 | out["processor_state"] = std::move(proc_out); |
| 226 | 226 | ||
| 227 | SaveToFile(std::move(out), GetPath("crash_report", title_id, timestamp)); | 227 | SaveToFile(out, GetPath("crash_report", title_id, timestamp)); |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | void Reporter::SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2, | 230 | void Reporter::SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2, |
| 231 | std::optional<std::vector<u8>> resolved_buffer) const { | 231 | const std::optional<std::vector<u8>>& resolved_buffer) const { |
| 232 | if (!IsReportingEnabled()) { | 232 | if (!IsReportingEnabled()) { |
| 233 | return; | 233 | return; |
| 234 | } | 234 | } |
| @@ -250,7 +250,7 @@ void Reporter::SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 | |||
| 250 | 250 | ||
| 251 | out["svc_break"] = std::move(break_out); | 251 | out["svc_break"] = std::move(break_out); |
| 252 | 252 | ||
| 253 | SaveToFile(std::move(out), GetPath("svc_break_report", title_id, timestamp)); | 253 | SaveToFile(out, GetPath("svc_break_report", title_id, timestamp)); |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id, | 256 | void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id, |
| @@ -271,13 +271,13 @@ void Reporter::SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u | |||
| 271 | 271 | ||
| 272 | out["function"] = std::move(function_out); | 272 | out["function"] = std::move(function_out); |
| 273 | 273 | ||
| 274 | SaveToFile(std::move(out), GetPath("unimpl_func_report", title_id, timestamp)); | 274 | SaveToFile(out, GetPath("unimpl_func_report", title_id, timestamp)); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | void Reporter::SaveUnimplementedAppletReport( | 277 | void Reporter::SaveUnimplementedAppletReport( |
| 278 | u32 applet_id, u32 common_args_version, u32 library_version, u32 theme_color, | 278 | u32 applet_id, u32 common_args_version, u32 library_version, u32 theme_color, |
| 279 | bool startup_sound, u64 system_tick, std::vector<std::vector<u8>> normal_channel, | 279 | bool startup_sound, u64 system_tick, const std::vector<std::vector<u8>>& normal_channel, |
| 280 | std::vector<std::vector<u8>> interactive_channel) const { | 280 | const std::vector<std::vector<u8>>& interactive_channel) const { |
| 281 | if (!IsReportingEnabled()) { | 281 | if (!IsReportingEnabled()) { |
| 282 | return; | 282 | return; |
| 283 | } | 283 | } |
| @@ -308,10 +308,11 @@ void Reporter::SaveUnimplementedAppletReport( | |||
| 308 | out["applet_normal_data"] = std::move(normal_out); | 308 | out["applet_normal_data"] = std::move(normal_out); |
| 309 | out["applet_interactive_data"] = std::move(interactive_out); | 309 | out["applet_interactive_data"] = std::move(interactive_out); |
| 310 | 310 | ||
| 311 | SaveToFile(std::move(out), GetPath("unimpl_applet_report", title_id, timestamp)); | 311 | SaveToFile(out, GetPath("unimpl_applet_report", title_id, timestamp)); |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | void Reporter::SavePlayReport(PlayReportType type, u64 title_id, std::vector<std::vector<u8>> data, | 314 | void Reporter::SavePlayReport(PlayReportType type, u64 title_id, |
| 315 | const std::vector<std::vector<u8>>& data, | ||
| 315 | std::optional<u64> process_id, std::optional<u128> user_id) const { | 316 | std::optional<u64> process_id, std::optional<u128> user_id) const { |
| 316 | if (!IsReportingEnabled()) { | 317 | if (!IsReportingEnabled()) { |
| 317 | return; | 318 | return; |
| @@ -335,12 +336,12 @@ void Reporter::SavePlayReport(PlayReportType type, u64 title_id, std::vector<std | |||
| 335 | out["play_report_type"] = fmt::format("{:02}", static_cast<u8>(type)); | 336 | out["play_report_type"] = fmt::format("{:02}", static_cast<u8>(type)); |
| 336 | out["play_report_data"] = std::move(data_out); | 337 | out["play_report_data"] = std::move(data_out); |
| 337 | 338 | ||
| 338 | SaveToFile(std::move(out), GetPath("play_report", title_id, timestamp)); | 339 | SaveToFile(out, GetPath("play_report", title_id, timestamp)); |
| 339 | } | 340 | } |
| 340 | 341 | ||
| 341 | void Reporter::SaveErrorReport(u64 title_id, Result result, | 342 | void Reporter::SaveErrorReport(u64 title_id, Result result, |
| 342 | std::optional<std::string> custom_text_main, | 343 | const std::optional<std::string>& custom_text_main, |
| 343 | std::optional<std::string> custom_text_detail) const { | 344 | const std::optional<std::string>& custom_text_detail) const { |
| 344 | if (!IsReportingEnabled()) { | 345 | if (!IsReportingEnabled()) { |
| 345 | return; | 346 | return; |
| 346 | } | 347 | } |
| @@ -354,11 +355,11 @@ void Reporter::SaveErrorReport(u64 title_id, Result result, | |||
| 354 | out["backtrace"] = GetBacktraceData(system); | 355 | out["backtrace"] = GetBacktraceData(system); |
| 355 | 356 | ||
| 356 | out["error_custom_text"] = { | 357 | out["error_custom_text"] = { |
| 357 | {"main", *custom_text_main}, | 358 | {"main", custom_text_main.value_or("")}, |
| 358 | {"detail", *custom_text_detail}, | 359 | {"detail", custom_text_detail.value_or("")}, |
| 359 | }; | 360 | }; |
| 360 | 361 | ||
| 361 | SaveToFile(std::move(out), GetPath("error_report", title_id, timestamp)); | 362 | SaveToFile(out, GetPath("error_report", title_id, timestamp)); |
| 362 | } | 363 | } |
| 363 | 364 | ||
| 364 | void Reporter::SaveFSAccessLog(std::string_view log_message) const { | 365 | void Reporter::SaveFSAccessLog(std::string_view log_message) const { |
diff --git a/src/core/reporter.h b/src/core/reporter.h index 68755cbde..9fdb9d6c1 100644 --- a/src/core/reporter.h +++ b/src/core/reporter.h | |||
| @@ -36,7 +36,7 @@ public: | |||
| 36 | 36 | ||
| 37 | // Used by syscall svcBreak | 37 | // Used by syscall svcBreak |
| 38 | void SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2, | 38 | void SaveSvcBreakReport(u32 type, bool signal_debugger, u64 info1, u64 info2, |
| 39 | std::optional<std::vector<u8>> resolved_buffer = {}) const; | 39 | const std::optional<std::vector<u8>>& resolved_buffer = {}) const; |
| 40 | 40 | ||
| 41 | // Used by HLE service handler | 41 | // Used by HLE service handler |
| 42 | void SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id, | 42 | void SaveUnimplementedFunctionReport(Kernel::HLERequestContext& ctx, u32 command_id, |
| @@ -44,10 +44,10 @@ public: | |||
| 44 | const std::string& service_name) const; | 44 | const std::string& service_name) const; |
| 45 | 45 | ||
| 46 | // Used by stub applet implementation | 46 | // Used by stub applet implementation |
| 47 | void SaveUnimplementedAppletReport(u32 applet_id, u32 common_args_version, u32 library_version, | 47 | void SaveUnimplementedAppletReport( |
| 48 | u32 theme_color, bool startup_sound, u64 system_tick, | 48 | u32 applet_id, u32 common_args_version, u32 library_version, u32 theme_color, |
| 49 | std::vector<std::vector<u8>> normal_channel, | 49 | bool startup_sound, u64 system_tick, const std::vector<std::vector<u8>>& normal_channel, |
| 50 | std::vector<std::vector<u8>> interactive_channel) const; | 50 | const std::vector<std::vector<u8>>& interactive_channel) const; |
| 51 | 51 | ||
| 52 | enum class PlayReportType { | 52 | enum class PlayReportType { |
| 53 | Old, | 53 | Old, |
| @@ -56,13 +56,13 @@ public: | |||
| 56 | System, | 56 | System, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | void SavePlayReport(PlayReportType type, u64 title_id, std::vector<std::vector<u8>> data, | 59 | void SavePlayReport(PlayReportType type, u64 title_id, const std::vector<std::vector<u8>>& data, |
| 60 | std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const; | 60 | std::optional<u64> process_id = {}, std::optional<u128> user_id = {}) const; |
| 61 | 61 | ||
| 62 | // Used by error applet | 62 | // Used by error applet |
| 63 | void SaveErrorReport(u64 title_id, Result result, | 63 | void SaveErrorReport(u64 title_id, Result result, |
| 64 | std::optional<std::string> custom_text_main = {}, | 64 | const std::optional<std::string>& custom_text_main = {}, |
| 65 | std::optional<std::string> custom_text_detail = {}) const; | 65 | const std::optional<std::string>& custom_text_detail = {}) const; |
| 66 | 66 | ||
| 67 | void SaveFSAccessLog(std::string_view log_message) const; | 67 | void SaveFSAccessLog(std::string_view log_message) const; |
| 68 | 68 | ||
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index abcf6eb11..8d5f2be2f 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -55,6 +55,8 @@ static const char* TranslateRenderer(Settings::RendererBackend backend) { | |||
| 55 | return "OpenGL"; | 55 | return "OpenGL"; |
| 56 | case Settings::RendererBackend::Vulkan: | 56 | case Settings::RendererBackend::Vulkan: |
| 57 | return "Vulkan"; | 57 | return "Vulkan"; |
| 58 | case Settings::RendererBackend::Null: | ||
| 59 | return "Null"; | ||
| 58 | } | 60 | } |
| 59 | return "Unknown"; | 61 | return "Unknown"; |
| 60 | } | 62 | } |
diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt index 2d9731f19..5bbe1d4b5 100644 --- a/src/dedicated_room/CMakeLists.txt +++ b/src/dedicated_room/CMakeLists.txt | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) | 4 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/CMakeModules) |
| 5 | 5 | ||
| 6 | add_executable(yuzu-room | 6 | add_executable(yuzu-room |
| 7 | precompiled_headers.h | ||
| 7 | yuzu_room.cpp | 8 | yuzu_room.cpp |
| 8 | yuzu_room.rc | 9 | yuzu_room.rc |
| 9 | ) | 10 | ) |
| @@ -25,3 +26,7 @@ target_link_libraries(yuzu-room PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) | |||
| 25 | if(UNIX AND NOT APPLE) | 26 | if(UNIX AND NOT APPLE) |
| 26 | install(TARGETS yuzu-room) | 27 | install(TARGETS yuzu-room) |
| 27 | endif() | 28 | endif() |
| 29 | |||
| 30 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 31 | target_precompile_headers(yuzu-room PRIVATE precompiled_headers.h) | ||
| 32 | endif() | ||
diff --git a/src/dedicated_room/precompiled_headers.h b/src/dedicated_room/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/dedicated_room/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index 193127d0a..7932aaab0 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt | |||
| @@ -34,6 +34,7 @@ add_library(input_common STATIC | |||
| 34 | input_poller.h | 34 | input_poller.h |
| 35 | main.cpp | 35 | main.cpp |
| 36 | main.h | 36 | main.h |
| 37 | precompiled_headers.h | ||
| 37 | ) | 38 | ) |
| 38 | 39 | ||
| 39 | if (MSVC) | 40 | if (MSVC) |
| @@ -55,15 +56,13 @@ if (ENABLE_SDL2) | |||
| 55 | drivers/sdl_driver.cpp | 56 | drivers/sdl_driver.cpp |
| 56 | drivers/sdl_driver.h | 57 | drivers/sdl_driver.h |
| 57 | ) | 58 | ) |
| 58 | if (YUZU_USE_EXTERNAL_SDL2) | 59 | target_link_libraries(input_common PRIVATE SDL2::SDL2) |
| 59 | target_link_libraries(input_common PRIVATE SDL2-static) | ||
| 60 | else() | ||
| 61 | target_link_libraries(input_common PRIVATE SDL2) | ||
| 62 | endif() | ||
| 63 | target_compile_definitions(input_common PRIVATE HAVE_SDL2) | 60 | target_compile_definitions(input_common PRIVATE HAVE_SDL2) |
| 64 | endif() | 61 | endif() |
| 65 | 62 | ||
| 66 | target_link_libraries(input_common PRIVATE usb) | ||
| 67 | |||
| 68 | create_target_directory_groups(input_common) | 63 | create_target_directory_groups(input_common) |
| 69 | target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost) | 64 | target_link_libraries(input_common PUBLIC core PRIVATE common Boost::boost libusb::usb) |
| 65 | |||
| 66 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 67 | target_precompile_headers(input_common PRIVATE precompiled_headers.h) | ||
| 68 | endif() | ||
diff --git a/src/input_common/drivers/gc_adapter.h b/src/input_common/drivers/gc_adapter.h index 7f81767f7..b5270fd0b 100644 --- a/src/input_common/drivers/gc_adapter.h +++ b/src/input_common/drivers/gc_adapter.h | |||
| @@ -5,10 +5,10 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <stop_token> | ||
| 9 | #include <string> | 8 | #include <string> |
| 10 | #include <thread> | 9 | #include <thread> |
| 11 | 10 | ||
| 11 | #include "common/polyfill_thread.h" | ||
| 12 | #include "input_common/input_engine.h" | 12 | #include "input_common/input_engine.h" |
| 13 | 13 | ||
| 14 | struct libusb_context; | 14 | struct libusb_context; |
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 98c3157a8..faf9cbdc3 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp | |||
| @@ -1,7 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <stop_token> | ||
| 5 | #include <thread> | 4 | #include <thread> |
| 6 | #include <fmt/format.h> | 5 | #include <fmt/format.h> |
| 7 | 6 | ||
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 286ce1cf6..72073cc23 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <stop_token> | ||
| 7 | #include <thread> | 6 | #include <thread> |
| 8 | 7 | ||
| 8 | #include "common/polyfill_thread.h" | ||
| 9 | #include "common/vector_math.h" | 9 | #include "common/vector_math.h" |
| 10 | #include "input_common/input_engine.h" | 10 | #include "input_common/input_engine.h" |
| 11 | 11 | ||
diff --git a/src/input_common/drivers/tas_input.cpp b/src/input_common/drivers/tas_input.cpp index 21c6ed405..f3ade90da 100644 --- a/src/input_common/drivers/tas_input.cpp +++ b/src/input_common/drivers/tas_input.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <cstring> | 4 | #include <cstring> |
| 5 | #include <sstream> | ||
| 5 | #include <fmt/format.h> | 6 | #include <fmt/format.h> |
| 6 | 7 | ||
| 7 | #include "common/fs/file.h" | 8 | #include "common/fs/file.h" |
diff --git a/src/input_common/drivers/virtual_amiibo.cpp b/src/input_common/drivers/virtual_amiibo.cpp index 564a188e5..63ffaca67 100644 --- a/src/input_common/drivers/virtual_amiibo.cpp +++ b/src/input_common/drivers/virtual_amiibo.cpp | |||
| @@ -47,20 +47,20 @@ Common::Input::NfcState VirtualAmiibo::SupportsNfc( | |||
| 47 | 47 | ||
| 48 | Common::Input::NfcState VirtualAmiibo::WriteNfcData( | 48 | Common::Input::NfcState VirtualAmiibo::WriteNfcData( |
| 49 | [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { | 49 | [[maybe_unused]] const PadIdentifier& identifier_, const std::vector<u8>& data) { |
| 50 | const Common::FS::IOFile amiibo_file{file_path, Common::FS::FileAccessMode::ReadWrite, | 50 | const Common::FS::IOFile nfc_file{file_path, Common::FS::FileAccessMode::ReadWrite, |
| 51 | Common::FS::FileType::BinaryFile}; | 51 | Common::FS::FileType::BinaryFile}; |
| 52 | 52 | ||
| 53 | if (!amiibo_file.IsOpen()) { | 53 | if (!nfc_file.IsOpen()) { |
| 54 | LOG_ERROR(Core, "Amiibo is already on use"); | 54 | LOG_ERROR(Core, "Amiibo is already on use"); |
| 55 | return Common::Input::NfcState::WriteFailed; | 55 | return Common::Input::NfcState::WriteFailed; |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | if (!amiibo_file.Write(data)) { | 58 | if (!nfc_file.Write(data)) { |
| 59 | LOG_ERROR(Service_NFP, "Error writting to file"); | 59 | LOG_ERROR(Service_NFP, "Error writting to file"); |
| 60 | return Common::Input::NfcState::WriteFailed; | 60 | return Common::Input::NfcState::WriteFailed; |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | amiibo_data = data; | 63 | nfc_data = data; |
| 64 | 64 | ||
| 65 | return Common::Input::NfcState::Success; | 65 | return Common::Input::NfcState::Success; |
| 66 | } | 66 | } |
| @@ -70,32 +70,44 @@ VirtualAmiibo::State VirtualAmiibo::GetCurrentState() const { | |||
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { | 72 | VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(const std::string& filename) { |
| 73 | const Common::FS::IOFile amiibo_file{filename, Common::FS::FileAccessMode::Read, | 73 | const Common::FS::IOFile nfc_file{filename, Common::FS::FileAccessMode::Read, |
| 74 | Common::FS::FileType::BinaryFile}; | 74 | Common::FS::FileType::BinaryFile}; |
| 75 | 75 | ||
| 76 | if (state != State::WaitingForAmiibo) { | 76 | if (state != State::WaitingForAmiibo) { |
| 77 | return Info::WrongDeviceState; | 77 | return Info::WrongDeviceState; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | if (!amiibo_file.IsOpen()) { | 80 | if (!nfc_file.IsOpen()) { |
| 81 | return Info::UnableToLoad; | 81 | return Info::UnableToLoad; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | amiibo_data.resize(amiibo_size); | 84 | switch (nfc_file.GetSize()) { |
| 85 | 85 | case AmiiboSize: | |
| 86 | if (amiibo_file.Read(amiibo_data) < amiibo_size_without_password) { | 86 | case AmiiboSizeWithoutPassword: |
| 87 | nfc_data.resize(AmiiboSize); | ||
| 88 | if (nfc_file.Read(nfc_data) < AmiiboSizeWithoutPassword) { | ||
| 89 | return Info::NotAnAmiibo; | ||
| 90 | } | ||
| 91 | break; | ||
| 92 | case MifareSize: | ||
| 93 | nfc_data.resize(MifareSize); | ||
| 94 | if (nfc_file.Read(nfc_data) < MifareSize) { | ||
| 95 | return Info::NotAnAmiibo; | ||
| 96 | } | ||
| 97 | break; | ||
| 98 | default: | ||
| 87 | return Info::NotAnAmiibo; | 99 | return Info::NotAnAmiibo; |
| 88 | } | 100 | } |
| 89 | 101 | ||
| 90 | file_path = filename; | 102 | file_path = filename; |
| 91 | state = State::AmiiboIsOpen; | 103 | state = State::AmiiboIsOpen; |
| 92 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); | 104 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); |
| 93 | return Info::Success; | 105 | return Info::Success; |
| 94 | } | 106 | } |
| 95 | 107 | ||
| 96 | VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { | 108 | VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { |
| 97 | if (state == State::AmiiboIsOpen) { | 109 | if (state == State::AmiiboIsOpen) { |
| 98 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, amiibo_data}); | 110 | SetNfc(identifier, {Common::Input::NfcState::NewAmiibo, nfc_data}); |
| 99 | return Info::Success; | 111 | return Info::Success; |
| 100 | } | 112 | } |
| 101 | 113 | ||
diff --git a/src/input_common/drivers/virtual_amiibo.h b/src/input_common/drivers/virtual_amiibo.h index 9baeb3997..0f9dad333 100644 --- a/src/input_common/drivers/virtual_amiibo.h +++ b/src/input_common/drivers/virtual_amiibo.h | |||
| @@ -53,12 +53,13 @@ public: | |||
| 53 | std::string GetLastFilePath() const; | 53 | std::string GetLastFilePath() const; |
| 54 | 54 | ||
| 55 | private: | 55 | private: |
| 56 | static constexpr std::size_t amiibo_size = 0x21C; | 56 | static constexpr std::size_t AmiiboSize = 0x21C; |
| 57 | static constexpr std::size_t amiibo_size_without_password = amiibo_size - 0x8; | 57 | static constexpr std::size_t AmiiboSizeWithoutPassword = AmiiboSize - 0x8; |
| 58 | static constexpr std::size_t MifareSize = 0x400; | ||
| 58 | 59 | ||
| 59 | std::string file_path{}; | 60 | std::string file_path{}; |
| 60 | State state{State::Initialized}; | 61 | State state{State::Initialized}; |
| 61 | std::vector<u8> amiibo_data; | 62 | std::vector<u8> nfc_data; |
| 62 | Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive}; | 63 | Common::Input::PollingMode polling_mode{Common::Input::PollingMode::Pasive}; |
| 63 | }; | 64 | }; |
| 64 | } // namespace InputCommon | 65 | } // namespace InputCommon |
diff --git a/src/input_common/precompiled_headers.h b/src/input_common/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/input_common/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt index 6f8ca4b90..1ab52da59 100644 --- a/src/network/CMakeLists.txt +++ b/src/network/CMakeLists.txt | |||
| @@ -8,6 +8,7 @@ add_library(network STATIC | |||
| 8 | network.h | 8 | network.h |
| 9 | packet.cpp | 9 | packet.cpp |
| 10 | packet.h | 10 | packet.h |
| 11 | precompiled_headers.h | ||
| 11 | room.cpp | 12 | room.cpp |
| 12 | room.h | 13 | room.h |
| 13 | room_member.cpp | 14 | room_member.cpp |
| @@ -18,8 +19,12 @@ add_library(network STATIC | |||
| 18 | 19 | ||
| 19 | create_target_directory_groups(network) | 20 | create_target_directory_groups(network) |
| 20 | 21 | ||
| 21 | target_link_libraries(network PRIVATE common enet Boost::boost) | 22 | target_link_libraries(network PRIVATE common enet::enet Boost::boost) |
| 22 | if (ENABLE_WEB_SERVICE) | 23 | if (ENABLE_WEB_SERVICE) |
| 23 | target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE) | 24 | target_compile_definitions(network PRIVATE -DENABLE_WEB_SERVICE) |
| 24 | target_link_libraries(network PRIVATE web_service) | 25 | target_link_libraries(network PRIVATE web_service) |
| 25 | endif() | 26 | endif() |
| 27 | |||
| 28 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 29 | target_precompile_headers(network PRIVATE precompiled_headers.h) | ||
| 30 | endif() | ||
diff --git a/src/network/precompiled_headers.h b/src/network/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/network/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 545d69c7e..525b2363c 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -221,6 +221,7 @@ add_library(shader_recompiler STATIC | |||
| 221 | ir_opt/dual_vertex_pass.cpp | 221 | ir_opt/dual_vertex_pass.cpp |
| 222 | ir_opt/global_memory_to_storage_buffer_pass.cpp | 222 | ir_opt/global_memory_to_storage_buffer_pass.cpp |
| 223 | ir_opt/identity_removal_pass.cpp | 223 | ir_opt/identity_removal_pass.cpp |
| 224 | ir_opt/layer_pass.cpp | ||
| 224 | ir_opt/lower_fp16_to_fp32.cpp | 225 | ir_opt/lower_fp16_to_fp32.cpp |
| 225 | ir_opt/lower_int64_to_int32.cpp | 226 | ir_opt/lower_int64_to_int32.cpp |
| 226 | ir_opt/passes.h | 227 | ir_opt/passes.h |
| @@ -230,6 +231,7 @@ add_library(shader_recompiler STATIC | |||
| 230 | ir_opt/texture_pass.cpp | 231 | ir_opt/texture_pass.cpp |
| 231 | ir_opt/verification_pass.cpp | 232 | ir_opt/verification_pass.cpp |
| 232 | object_pool.h | 233 | object_pool.h |
| 234 | precompiled_headers.h | ||
| 233 | profile.h | 235 | profile.h |
| 234 | program_header.h | 236 | program_header.h |
| 235 | runtime_info.h | 237 | runtime_info.h |
| @@ -254,7 +256,12 @@ else() | |||
| 254 | # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. | 256 | # Bracket depth determines maximum size of a fold expression in Clang since 9c9974c3ccb6. |
| 255 | # And this in turns limits the size of a std::array. | 257 | # And this in turns limits the size of a std::array. |
| 256 | $<$<CXX_COMPILER_ID:Clang>:-fbracket-depth=1024> | 258 | $<$<CXX_COMPILER_ID:Clang>:-fbracket-depth=1024> |
| 259 | $<$<CXX_COMPILER_ID:AppleClang>:-fbracket-depth=1024> | ||
| 257 | ) | 260 | ) |
| 258 | endif() | 261 | endif() |
| 259 | 262 | ||
| 260 | create_target_directory_groups(shader_recompiler) | 263 | create_target_directory_groups(shader_recompiler) |
| 264 | |||
| 265 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 266 | target_precompile_headers(shader_recompiler PRIVATE precompiled_headers.h) | ||
| 267 | endif() | ||
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 265ac9c85..0f86a8004 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
| @@ -402,8 +402,10 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | |||
| 402 | ctx.AddCapability(spv::Capability::SparseResidency); | 402 | ctx.AddCapability(spv::Capability::SparseResidency); |
| 403 | } | 403 | } |
| 404 | if (info.uses_demote_to_helper_invocation && profile.support_demote_to_helper_invocation) { | 404 | if (info.uses_demote_to_helper_invocation && profile.support_demote_to_helper_invocation) { |
| 405 | ctx.AddExtension("SPV_EXT_demote_to_helper_invocation"); | 405 | if (profile.supported_spirv < 0x00010600) { |
| 406 | ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); | 406 | ctx.AddExtension("SPV_EXT_demote_to_helper_invocation"); |
| 407 | } | ||
| 408 | ctx.AddCapability(spv::Capability::DemoteToHelperInvocation); | ||
| 407 | } | 409 | } |
| 408 | if (info.stores[IR::Attribute::ViewportIndex]) { | 410 | if (info.stores[IR::Attribute::ViewportIndex]) { |
| 409 | ctx.AddCapability(spv::Capability::MultiViewport); | 411 | ctx.AddCapability(spv::Capability::MultiViewport); |
| @@ -426,12 +428,11 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct | |||
| 426 | if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id || | 428 | if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id || |
| 427 | info.uses_subgroup_shuffles) && | 429 | info.uses_subgroup_shuffles) && |
| 428 | profile.support_vote) { | 430 | profile.support_vote) { |
| 429 | ctx.AddExtension("SPV_KHR_shader_ballot"); | 431 | ctx.AddCapability(spv::Capability::GroupNonUniformBallot); |
| 430 | ctx.AddCapability(spv::Capability::SubgroupBallotKHR); | 432 | ctx.AddCapability(spv::Capability::GroupNonUniformShuffle); |
| 431 | if (!profile.warp_size_potentially_larger_than_guest) { | 433 | if (!profile.warp_size_potentially_larger_than_guest) { |
| 432 | // vote ops are only used when not taking the long path | 434 | // vote ops are only used when not taking the long path |
| 433 | ctx.AddExtension("SPV_KHR_subgroup_vote"); | 435 | ctx.AddCapability(spv::Capability::GroupNonUniformVote); |
| 434 | ctx.AddCapability(spv::Capability::SubgroupVoteKHR); | ||
| 435 | } | 436 | } |
| 436 | } | 437 | } |
| 437 | if (info.uses_int64_bit_atomics && profile.support_int64_atomics) { | 438 | if (info.uses_int64_bit_atomics && profile.support_int64_atomics) { |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp index 7ad0b08ac..fb2c792c1 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp | |||
| @@ -12,7 +12,7 @@ void EmitJoin(EmitContext&) { | |||
| 12 | 12 | ||
| 13 | void EmitDemoteToHelperInvocation(EmitContext& ctx) { | 13 | void EmitDemoteToHelperInvocation(EmitContext& ctx) { |
| 14 | if (ctx.profile.support_demote_to_helper_invocation) { | 14 | if (ctx.profile.support_demote_to_helper_invocation) { |
| 15 | ctx.OpDemoteToHelperInvocationEXT(); | 15 | ctx.OpDemoteToHelperInvocation(); |
| 16 | } else { | 16 | } else { |
| 17 | const Id kill_label{ctx.OpLabel()}; | 17 | const Id kill_label{ctx.OpLabel()}; |
| 18 | const Id impossible_label{ctx.OpLabel()}; | 18 | const Id impossible_label{ctx.OpLabel()}; |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index 7cbbbfaa6..2c90f2368 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | namespace Shader::Backend::SPIRV { | 7 | namespace Shader::Backend::SPIRV { |
| 8 | namespace { | 8 | namespace { |
| 9 | Id SubgroupScope(EmitContext& ctx) { | ||
| 10 | return ctx.Const(static_cast<u32>(spv::Scope::Subgroup)); | ||
| 11 | } | ||
| 12 | |||
| 9 | Id GetThreadId(EmitContext& ctx) { | 13 | Id GetThreadId(EmitContext& ctx) { |
| 10 | return ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id); | 14 | return ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id); |
| 11 | } | 15 | } |
| @@ -49,8 +53,9 @@ Id GetMaxThreadId(EmitContext& ctx, Id thread_id, Id clamp, Id segmentation_mask | |||
| 49 | } | 53 | } |
| 50 | 54 | ||
| 51 | Id SelectValue(EmitContext& ctx, Id in_range, Id value, Id src_thread_id) { | 55 | Id SelectValue(EmitContext& ctx, Id in_range, Id value, Id src_thread_id) { |
| 52 | return ctx.OpSelect(ctx.U32[1], in_range, | 56 | return ctx.OpSelect( |
| 53 | ctx.OpSubgroupReadInvocationKHR(ctx.U32[1], value, src_thread_id), value); | 57 | ctx.U32[1], in_range, |
| 58 | ctx.OpGroupNonUniformShuffle(ctx.U32[1], SubgroupScope(ctx), value, src_thread_id), value); | ||
| 54 | } | 59 | } |
| 55 | 60 | ||
| 56 | Id GetUpperClamp(EmitContext& ctx, Id invocation_id, Id clamp) { | 61 | Id GetUpperClamp(EmitContext& ctx, Id invocation_id, Id clamp) { |
| @@ -71,40 +76,46 @@ Id EmitLaneId(EmitContext& ctx) { | |||
| 71 | 76 | ||
| 72 | Id EmitVoteAll(EmitContext& ctx, Id pred) { | 77 | Id EmitVoteAll(EmitContext& ctx, Id pred) { |
| 73 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { | 78 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
| 74 | return ctx.OpSubgroupAllKHR(ctx.U1, pred); | 79 | return ctx.OpGroupNonUniformAll(ctx.U1, SubgroupScope(ctx), pred); |
| 75 | } | 80 | } |
| 76 | const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)}; | 81 | const Id mask_ballot{ |
| 82 | ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), ctx.true_value)}; | ||
| 77 | const Id active_mask{WarpExtract(ctx, mask_ballot)}; | 83 | const Id active_mask{WarpExtract(ctx, mask_ballot)}; |
| 78 | const Id ballot{WarpExtract(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))}; | 84 | const Id ballot{ |
| 85 | WarpExtract(ctx, ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred))}; | ||
| 79 | const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)}; | 86 | const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)}; |
| 80 | return ctx.OpIEqual(ctx.U1, lhs, active_mask); | 87 | return ctx.OpIEqual(ctx.U1, lhs, active_mask); |
| 81 | } | 88 | } |
| 82 | 89 | ||
| 83 | Id EmitVoteAny(EmitContext& ctx, Id pred) { | 90 | Id EmitVoteAny(EmitContext& ctx, Id pred) { |
| 84 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { | 91 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
| 85 | return ctx.OpSubgroupAnyKHR(ctx.U1, pred); | 92 | return ctx.OpGroupNonUniformAny(ctx.U1, SubgroupScope(ctx), pred); |
| 86 | } | 93 | } |
| 87 | const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)}; | 94 | const Id mask_ballot{ |
| 95 | ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), ctx.true_value)}; | ||
| 88 | const Id active_mask{WarpExtract(ctx, mask_ballot)}; | 96 | const Id active_mask{WarpExtract(ctx, mask_ballot)}; |
| 89 | const Id ballot{WarpExtract(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))}; | 97 | const Id ballot{ |
| 98 | WarpExtract(ctx, ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred))}; | ||
| 90 | const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)}; | 99 | const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)}; |
| 91 | return ctx.OpINotEqual(ctx.U1, lhs, ctx.u32_zero_value); | 100 | return ctx.OpINotEqual(ctx.U1, lhs, ctx.u32_zero_value); |
| 92 | } | 101 | } |
| 93 | 102 | ||
| 94 | Id EmitVoteEqual(EmitContext& ctx, Id pred) { | 103 | Id EmitVoteEqual(EmitContext& ctx, Id pred) { |
| 95 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { | 104 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
| 96 | return ctx.OpSubgroupAllEqualKHR(ctx.U1, pred); | 105 | return ctx.OpGroupNonUniformAllEqual(ctx.U1, SubgroupScope(ctx), pred); |
| 97 | } | 106 | } |
| 98 | const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)}; | 107 | const Id mask_ballot{ |
| 108 | ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), ctx.true_value)}; | ||
| 99 | const Id active_mask{WarpExtract(ctx, mask_ballot)}; | 109 | const Id active_mask{WarpExtract(ctx, mask_ballot)}; |
| 100 | const Id ballot{WarpExtract(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))}; | 110 | const Id ballot{ |
| 111 | WarpExtract(ctx, ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred))}; | ||
| 101 | const Id lhs{ctx.OpBitwiseXor(ctx.U32[1], ballot, active_mask)}; | 112 | const Id lhs{ctx.OpBitwiseXor(ctx.U32[1], ballot, active_mask)}; |
| 102 | return ctx.OpLogicalOr(ctx.U1, ctx.OpIEqual(ctx.U1, lhs, ctx.u32_zero_value), | 113 | return ctx.OpLogicalOr(ctx.U1, ctx.OpIEqual(ctx.U1, lhs, ctx.u32_zero_value), |
| 103 | ctx.OpIEqual(ctx.U1, lhs, active_mask)); | 114 | ctx.OpIEqual(ctx.U1, lhs, active_mask)); |
| 104 | } | 115 | } |
| 105 | 116 | ||
| 106 | Id EmitSubgroupBallot(EmitContext& ctx, Id pred) { | 117 | Id EmitSubgroupBallot(EmitContext& ctx, Id pred) { |
| 107 | const Id ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], pred)}; | 118 | const Id ballot{ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred)}; |
| 108 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { | 119 | if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
| 109 | return ctx.OpCompositeExtract(ctx.U32[1], ballot, 0U); | 120 | return ctx.OpCompositeExtract(ctx.U32[1], ballot, 0U); |
| 110 | } | 121 | } |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.h b/src/shader_recompiler/frontend/ir/opcodes.h index e70d7745c..d155afd0f 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.h +++ b/src/shader_recompiler/frontend/ir/opcodes.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #include <fmt/format.h> | 9 | #include <fmt/format.h> |
| 10 | 10 | ||
| 11 | #include "common/polyfill_ranges.h" | ||
| 11 | #include "shader_recompiler/frontend/ir/type.h" | 12 | #include "shader_recompiler/frontend/ir/type.h" |
| 12 | 13 | ||
| 13 | namespace Shader::IR { | 14 | namespace Shader::IR { |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index e8bbb93a5..8b34356fd 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include "shader_recompiler/frontend/ir/pred.h" | 23 | #include "shader_recompiler/frontend/ir/pred.h" |
| 24 | #include "shader_recompiler/frontend/ir/reg.h" | 24 | #include "shader_recompiler/frontend/ir/reg.h" |
| 25 | #include "shader_recompiler/frontend/ir/type.h" | 25 | #include "shader_recompiler/frontend/ir/type.h" |
| 26 | #include "shader_recompiler/frontend/ir/value.h" | ||
| 27 | 26 | ||
| 28 | namespace Shader::IR { | 27 | namespace Shader::IR { |
| 29 | 28 | ||
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp index 6939692cd..dce414cb4 100644 --- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include <fmt/format.h> | 10 | #include <fmt/format.h> |
| 11 | 11 | ||
| 12 | #include "common/polyfill_ranges.h" | ||
| 12 | #include "shader_recompiler/exception.h" | 13 | #include "shader_recompiler/exception.h" |
| 13 | #include "shader_recompiler/frontend/maxwell/control_flow.h" | 14 | #include "shader_recompiler/frontend/maxwell/control_flow.h" |
| 14 | #include "shader_recompiler/frontend/maxwell/decode.h" | 15 | #include "shader_recompiler/frontend/maxwell/decode.h" |
diff --git a/src/shader_recompiler/frontend/maxwell/decode.cpp b/src/shader_recompiler/frontend/maxwell/decode.cpp index 455c91470..774f65bc5 100644 --- a/src/shader_recompiler/frontend/maxwell/decode.cpp +++ b/src/shader_recompiler/frontend/maxwell/decode.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "shader_recompiler/exception.h" | 11 | #include "shader_recompiler/exception.h" |
| 11 | #include "shader_recompiler/frontend/maxwell/decode.h" | 12 | #include "shader_recompiler/frontend/maxwell/decode.h" |
| 12 | #include "shader_recompiler/frontend/maxwell/opcodes.h" | 13 | #include "shader_recompiler/frontend/maxwell/opcodes.h" |
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index ce42475d4..80c90fe6a 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include <boost/intrusive/list.hpp> | 13 | #include <boost/intrusive/list.hpp> |
| 14 | 14 | ||
| 15 | #include "common/polyfill_ranges.h" | ||
| 15 | #include "shader_recompiler/environment.h" | 16 | #include "shader_recompiler/environment.h" |
| 16 | #include "shader_recompiler/frontend/ir/basic_block.h" | 17 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 17 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | 18 | #include "shader_recompiler/frontend/ir/ir_emitter.h" |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp index 4942878b9..85c18d942 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/floating_point_conversion_integer.cpp | |||
| @@ -176,12 +176,13 @@ void TranslateF2I(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a) { | |||
| 176 | (f2i.src_format == SrcFormat::F64) != (f2i.dest_format == DestFormat::I64); | 176 | (f2i.src_format == SrcFormat::F64) != (f2i.dest_format == DestFormat::I64); |
| 177 | if (special_nan_cases) { | 177 | if (special_nan_cases) { |
| 178 | if (f2i.dest_format == DestFormat::I32) { | 178 | if (f2i.dest_format == DestFormat::I32) { |
| 179 | constexpr u32 nan_value = 0x8000'0000U; | ||
| 179 | handled_special_case = true; | 180 | handled_special_case = true; |
| 180 | result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(0x8000'0000U), result)}; | 181 | result = IR::U32{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm32(nan_value), result)}; |
| 181 | } else if (f2i.dest_format == DestFormat::I64) { | 182 | } else if (f2i.dest_format == DestFormat::I64) { |
| 183 | constexpr u64 nan_value = 0x8000'0000'0000'0000ULL; | ||
| 182 | handled_special_case = true; | 184 | handled_special_case = true; |
| 183 | result = IR::U64{ | 185 | result = IR::U64{v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(nan_value), result)}; |
| 184 | v.ir.Select(v.ir.FPIsNan(op_a), v.ir.Imm64(0x8000'0000'0000'0000UL), result)}; | ||
| 185 | } | 186 | } |
| 186 | } | 187 | } |
| 187 | if (!handled_special_case && is_signed) { | 188 | if (!handled_special_case && is_signed) { |
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp index 376aae0ea..3adbd2b16 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/settings.h" | 9 | #include "common/settings.h" |
| 10 | #include "shader_recompiler/exception.h" | 10 | #include "shader_recompiler/exception.h" |
| 11 | #include "shader_recompiler/frontend/ir/basic_block.h" | 11 | #include "shader_recompiler/frontend/ir/basic_block.h" |
| 12 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 12 | #include "shader_recompiler/frontend/ir/post_order.h" | 13 | #include "shader_recompiler/frontend/ir/post_order.h" |
| 13 | #include "shader_recompiler/frontend/maxwell/structured_control_flow.h" | 14 | #include "shader_recompiler/frontend/maxwell/structured_control_flow.h" |
| 14 | #include "shader_recompiler/frontend/maxwell/translate/translate.h" | 15 | #include "shader_recompiler/frontend/maxwell/translate/translate.h" |
| @@ -233,6 +234,8 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo | |||
| 233 | Optimization::VerificationPass(program); | 234 | Optimization::VerificationPass(program); |
| 234 | } | 235 | } |
| 235 | Optimization::CollectShaderInfoPass(env, program); | 236 | Optimization::CollectShaderInfoPass(env, program); |
| 237 | Optimization::LayerPass(program, host_info); | ||
| 238 | |||
| 236 | CollectInterpolationInfo(env, program); | 239 | CollectInterpolationInfo(env, program); |
| 237 | AddNVNStorageBuffers(program); | 240 | AddNVNStorageBuffers(program); |
| 238 | return program; | 241 | return program; |
| @@ -331,4 +334,82 @@ void ConvertLegacyToGeneric(IR::Program& program, const Shader::RuntimeInfo& run | |||
| 331 | } | 334 | } |
| 332 | } | 335 | } |
| 333 | 336 | ||
| 337 | IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool, | ||
| 338 | ObjectPool<IR::Block>& block_pool, | ||
| 339 | const HostTranslateInfo& host_info, | ||
| 340 | IR::Program& source_program, | ||
| 341 | Shader::OutputTopology output_topology) { | ||
| 342 | IR::Program program; | ||
| 343 | program.stage = Stage::Geometry; | ||
| 344 | program.output_topology = output_topology; | ||
| 345 | switch (output_topology) { | ||
| 346 | case OutputTopology::PointList: | ||
| 347 | program.output_vertices = 1; | ||
| 348 | break; | ||
| 349 | case OutputTopology::LineStrip: | ||
| 350 | program.output_vertices = 2; | ||
| 351 | break; | ||
| 352 | default: | ||
| 353 | program.output_vertices = 3; | ||
| 354 | break; | ||
| 355 | } | ||
| 356 | |||
| 357 | program.is_geometry_passthrough = false; | ||
| 358 | program.info.loads.mask = source_program.info.stores.mask; | ||
| 359 | program.info.stores.mask = source_program.info.stores.mask; | ||
| 360 | program.info.stores.Set(IR::Attribute::Layer, true); | ||
| 361 | program.info.stores.Set(source_program.info.emulated_layer, false); | ||
| 362 | |||
| 363 | IR::Block* current_block = block_pool.Create(inst_pool); | ||
| 364 | auto& node{program.syntax_list.emplace_back()}; | ||
| 365 | node.type = IR::AbstractSyntaxNode::Type::Block; | ||
| 366 | node.data.block = current_block; | ||
| 367 | |||
| 368 | IR::IREmitter ir{*current_block}; | ||
| 369 | for (u32 i = 0; i < program.output_vertices; i++) { | ||
| 370 | // Assign generics from input | ||
| 371 | for (u32 j = 0; j < 32; j++) { | ||
| 372 | if (!program.info.stores.Generic(j)) { | ||
| 373 | continue; | ||
| 374 | } | ||
| 375 | |||
| 376 | const IR::Attribute attr = IR::Attribute::Generic0X + (j * 4); | ||
| 377 | ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); | ||
| 378 | ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); | ||
| 379 | ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); | ||
| 380 | ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); | ||
| 381 | } | ||
| 382 | |||
| 383 | // Assign position from input | ||
| 384 | const IR::Attribute attr = IR::Attribute::PositionX; | ||
| 385 | ir.SetAttribute(attr + 0, ir.GetAttribute(attr + 0, ir.Imm32(i)), ir.Imm32(0)); | ||
| 386 | ir.SetAttribute(attr + 1, ir.GetAttribute(attr + 1, ir.Imm32(i)), ir.Imm32(0)); | ||
| 387 | ir.SetAttribute(attr + 2, ir.GetAttribute(attr + 2, ir.Imm32(i)), ir.Imm32(0)); | ||
| 388 | ir.SetAttribute(attr + 3, ir.GetAttribute(attr + 3, ir.Imm32(i)), ir.Imm32(0)); | ||
| 389 | |||
| 390 | // Assign layer | ||
| 391 | ir.SetAttribute(IR::Attribute::Layer, ir.GetAttribute(source_program.info.emulated_layer), | ||
| 392 | ir.Imm32(0)); | ||
| 393 | |||
| 394 | // Emit vertex | ||
| 395 | ir.EmitVertex(ir.Imm32(0)); | ||
| 396 | } | ||
| 397 | ir.EndPrimitive(ir.Imm32(0)); | ||
| 398 | |||
| 399 | IR::Block* return_block{block_pool.Create(inst_pool)}; | ||
| 400 | IR::IREmitter{*return_block}.Epilogue(); | ||
| 401 | current_block->AddBranch(return_block); | ||
| 402 | |||
| 403 | auto& merge{program.syntax_list.emplace_back()}; | ||
| 404 | merge.type = IR::AbstractSyntaxNode::Type::Block; | ||
| 405 | merge.data.block = return_block; | ||
| 406 | program.syntax_list.emplace_back().type = IR::AbstractSyntaxNode::Type::Return; | ||
| 407 | |||
| 408 | program.blocks = GenerateBlocks(program.syntax_list); | ||
| 409 | program.post_order_blocks = PostOrder(program.syntax_list.front()); | ||
| 410 | Optimization::SsaRewritePass(program); | ||
| 411 | |||
| 412 | return program; | ||
| 413 | } | ||
| 414 | |||
| 334 | } // namespace Shader::Maxwell | 415 | } // namespace Shader::Maxwell |
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.h b/src/shader_recompiler/frontend/maxwell/translate_program.h index 02ede8c9c..497afe7cb 100644 --- a/src/shader_recompiler/frontend/maxwell/translate_program.h +++ b/src/shader_recompiler/frontend/maxwell/translate_program.h | |||
| @@ -25,4 +25,13 @@ namespace Shader::Maxwell { | |||
| 25 | 25 | ||
| 26 | void ConvertLegacyToGeneric(IR::Program& program, const RuntimeInfo& runtime_info); | 26 | void ConvertLegacyToGeneric(IR::Program& program, const RuntimeInfo& runtime_info); |
| 27 | 27 | ||
| 28 | // Maxwell v1 and older Nvidia cards don't support setting gl_Layer from non-geometry stages. | ||
| 29 | // This creates a workaround by setting the layer as a generic output and creating a | ||
| 30 | // passthrough geometry shader that reads the generic and sets the layer. | ||
| 31 | [[nodiscard]] IR::Program GenerateGeometryPassthrough(ObjectPool<IR::Inst>& inst_pool, | ||
| 32 | ObjectPool<IR::Block>& block_pool, | ||
| 33 | const HostTranslateInfo& host_info, | ||
| 34 | IR::Program& source_program, | ||
| 35 | Shader::OutputTopology output_topology); | ||
| 36 | |||
| 28 | } // namespace Shader::Maxwell | 37 | } // namespace Shader::Maxwell |
diff --git a/src/shader_recompiler/host_translate_info.h b/src/shader_recompiler/host_translate_info.h index cc1500690..d5d279554 100644 --- a/src/shader_recompiler/host_translate_info.h +++ b/src/shader_recompiler/host_translate_info.h | |||
| @@ -13,7 +13,8 @@ struct HostTranslateInfo { | |||
| 13 | bool support_float16{}; ///< True when the device supports 16-bit floats | 13 | bool support_float16{}; ///< True when the device supports 16-bit floats |
| 14 | bool support_int64{}; ///< True when the device supports 64-bit integers | 14 | bool support_int64{}; ///< True when the device supports 64-bit integers |
| 15 | bool needs_demote_reorder{}; ///< True when the device needs DemoteToHelperInvocation reordered | 15 | bool needs_demote_reorder{}; ///< True when the device needs DemoteToHelperInvocation reordered |
| 16 | bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers | 16 | bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers |
| 17 | bool support_viewport_index_layer{}; ///< True when the device supports gl_Layer in VS | ||
| 17 | }; | 18 | }; |
| 18 | 19 | ||
| 19 | } // namespace Shader | 20 | } // namespace Shader |
diff --git a/src/shader_recompiler/ir_opt/layer_pass.cpp b/src/shader_recompiler/ir_opt/layer_pass.cpp new file mode 100644 index 000000000..4574f7cf2 --- /dev/null +++ b/src/shader_recompiler/ir_opt/layer_pass.cpp | |||
| @@ -0,0 +1,68 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <algorithm> | ||
| 5 | #include <bit> | ||
| 6 | #include <optional> | ||
| 7 | |||
| 8 | #include <boost/container/small_vector.hpp> | ||
| 9 | |||
| 10 | #include "shader_recompiler/environment.h" | ||
| 11 | #include "shader_recompiler/frontend/ir/basic_block.h" | ||
| 12 | #include "shader_recompiler/frontend/ir/breadth_first_search.h" | ||
| 13 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||
| 14 | #include "shader_recompiler/host_translate_info.h" | ||
| 15 | #include "shader_recompiler/ir_opt/passes.h" | ||
| 16 | #include "shader_recompiler/shader_info.h" | ||
| 17 | |||
| 18 | namespace Shader::Optimization { | ||
| 19 | |||
| 20 | static IR::Attribute EmulatedLayerAttribute(VaryingState& stores) { | ||
| 21 | for (u32 i = 0; i < 32; i++) { | ||
| 22 | if (!stores.Generic(i)) { | ||
| 23 | return IR::Attribute::Generic0X + (i * 4); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | return IR::Attribute::Layer; | ||
| 27 | } | ||
| 28 | |||
| 29 | static bool PermittedProgramStage(Stage stage) { | ||
| 30 | switch (stage) { | ||
| 31 | case Stage::VertexA: | ||
| 32 | case Stage::VertexB: | ||
| 33 | case Stage::TessellationControl: | ||
| 34 | case Stage::TessellationEval: | ||
| 35 | return true; | ||
| 36 | default: | ||
| 37 | return false; | ||
| 38 | } | ||
| 39 | } | ||
| 40 | |||
| 41 | void LayerPass(IR::Program& program, const HostTranslateInfo& host_info) { | ||
| 42 | if (host_info.support_viewport_index_layer || !PermittedProgramStage(program.stage)) { | ||
| 43 | return; | ||
| 44 | } | ||
| 45 | |||
| 46 | const auto end{program.post_order_blocks.end()}; | ||
| 47 | const auto layer_attribute = EmulatedLayerAttribute(program.info.stores); | ||
| 48 | bool requires_layer_emulation = false; | ||
| 49 | |||
| 50 | for (auto block = program.post_order_blocks.begin(); block != end; ++block) { | ||
| 51 | for (IR::Inst& inst : (*block)->Instructions()) { | ||
| 52 | if (inst.GetOpcode() == IR::Opcode::SetAttribute && | ||
| 53 | inst.Arg(0).Attribute() == IR::Attribute::Layer) { | ||
| 54 | requires_layer_emulation = true; | ||
| 55 | inst.SetArg(0, IR::Value{layer_attribute}); | ||
| 56 | } | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | if (requires_layer_emulation) { | ||
| 61 | program.info.requires_layer_emulation = true; | ||
| 62 | program.info.emulated_layer = layer_attribute; | ||
| 63 | program.info.stores.Set(IR::Attribute::Layer, false); | ||
| 64 | program.info.stores.Set(layer_attribute, true); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | } // namespace Shader::Optimization | ||
diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h index 586a0668f..11bfe801a 100644 --- a/src/shader_recompiler/ir_opt/passes.h +++ b/src/shader_recompiler/ir_opt/passes.h | |||
| @@ -23,6 +23,7 @@ void RescalingPass(IR::Program& program); | |||
| 23 | void SsaRewritePass(IR::Program& program); | 23 | void SsaRewritePass(IR::Program& program); |
| 24 | void PositionPass(Environment& env, IR::Program& program); | 24 | void PositionPass(Environment& env, IR::Program& program); |
| 25 | void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info); | 25 | void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info); |
| 26 | void LayerPass(IR::Program& program, const HostTranslateInfo& host_info); | ||
| 26 | void VerificationPass(const IR::Program& program); | 27 | void VerificationPass(const IR::Program& program); |
| 27 | 28 | ||
| 28 | // Dual Vertex | 29 | // Dual Vertex |
diff --git a/src/shader_recompiler/precompiled_headers.h b/src/shader_recompiler/precompiled_headers.h new file mode 100644 index 000000000..5dd6b7eca --- /dev/null +++ b/src/shader_recompiler/precompiled_headers.h | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
| 7 | #include "frontend/maxwell/translate/impl/impl.h" | ||
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index ee6252bb5..d9c6e92db 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -204,6 +204,9 @@ struct Info { | |||
| 204 | u32 nvn_buffer_base{}; | 204 | u32 nvn_buffer_base{}; |
| 205 | std::bitset<16> nvn_buffer_used{}; | 205 | std::bitset<16> nvn_buffer_used{}; |
| 206 | 206 | ||
| 207 | bool requires_layer_emulation{}; | ||
| 208 | IR::Attribute emulated_layer{}; | ||
| 209 | |||
| 207 | boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS> | 210 | boost::container::static_vector<ConstantBufferDescriptor, MAX_CBUFS> |
| 208 | constant_buffer_descriptors; | 211 | constant_buffer_descriptors; |
| 209 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; | 212 | boost::container::static_vector<StorageBufferDescriptor, MAX_SSBOS> storage_buffers_descriptors; |
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 43ad2c7ff..348d1edf4 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt | |||
| @@ -11,6 +11,7 @@ add_executable(tests | |||
| 11 | common/unique_function.cpp | 11 | common/unique_function.cpp |
| 12 | core/core_timing.cpp | 12 | core/core_timing.cpp |
| 13 | core/internal_network/network.cpp | 13 | core/internal_network/network.cpp |
| 14 | precompiled_headers.h | ||
| 14 | tests.cpp | 15 | tests.cpp |
| 15 | video_core/buffer_base.cpp | 16 | video_core/buffer_base.cpp |
| 16 | input_common/calibration_configuration_job.cpp | 17 | input_common/calibration_configuration_job.cpp |
| @@ -22,3 +23,7 @@ target_link_libraries(tests PRIVATE common core input_common) | |||
| 22 | target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} Catch2::Catch2 Threads::Threads) | 23 | target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} Catch2::Catch2 Threads::Threads) |
| 23 | 24 | ||
| 24 | add_test(NAME tests COMMAND tests) | 25 | add_test(NAME tests COMMAND tests) |
| 26 | |||
| 27 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 28 | target_precompile_headers(tests PRIVATE precompiled_headers.h) | ||
| 29 | endif() | ||
diff --git a/src/tests/precompiled_headers.h b/src/tests/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/tests/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index b03a30992..5096d935e 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -84,6 +84,7 @@ add_library(video_core STATIC | |||
| 84 | gpu_thread.h | 84 | gpu_thread.h |
| 85 | memory_manager.cpp | 85 | memory_manager.cpp |
| 86 | memory_manager.h | 86 | memory_manager.h |
| 87 | precompiled_headers.h | ||
| 87 | pte_kind.h | 88 | pte_kind.h |
| 88 | query_cache.h | 89 | query_cache.h |
| 89 | rasterizer_accelerated.cpp | 90 | rasterizer_accelerated.cpp |
| @@ -91,6 +92,10 @@ add_library(video_core STATIC | |||
| 91 | rasterizer_interface.h | 92 | rasterizer_interface.h |
| 92 | renderer_base.cpp | 93 | renderer_base.cpp |
| 93 | renderer_base.h | 94 | renderer_base.h |
| 95 | renderer_null/null_rasterizer.cpp | ||
| 96 | renderer_null/null_rasterizer.h | ||
| 97 | renderer_null/renderer_null.cpp | ||
| 98 | renderer_null/renderer_null.h | ||
| 94 | renderer_opengl/gl_buffer_cache.cpp | 99 | renderer_opengl/gl_buffer_cache.cpp |
| 95 | renderer_opengl/gl_buffer_cache.h | 100 | renderer_opengl/gl_buffer_cache.h |
| 96 | renderer_opengl/gl_compute_pipeline.cpp | 101 | renderer_opengl/gl_compute_pipeline.cpp |
| @@ -259,8 +264,7 @@ target_link_options(video_core PRIVATE ${FFmpeg_LDFLAGS}) | |||
| 259 | 264 | ||
| 260 | add_dependencies(video_core host_shaders) | 265 | add_dependencies(video_core host_shaders) |
| 261 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) | 266 | target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) |
| 262 | target_include_directories(video_core PRIVATE sirit ../../externals/Vulkan-Headers/include) | 267 | target_link_libraries(video_core PRIVATE sirit Vulkan::Headers) |
| 263 | target_link_libraries(video_core PRIVATE sirit) | ||
| 264 | 268 | ||
| 265 | if (ENABLE_NSIGHT_AFTERMATH) | 269 | if (ENABLE_NSIGHT_AFTERMATH) |
| 266 | if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) | 270 | if (NOT DEFINED ENV{NSIGHT_AFTERMATH_SDK}) |
| @@ -279,9 +283,15 @@ if (MSVC) | |||
| 279 | /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data | 283 | /we4244 # 'conversion': conversion from 'type1' to 'type2', possible loss of data |
| 280 | ) | 284 | ) |
| 281 | else() | 285 | else() |
| 282 | target_compile_options(video_core PRIVATE | 286 | if (APPLE) |
| 283 | -Werror=conversion | 287 | # error: declaration shadows a typedef in 'interval_base_set<SubType, DomainT, Compare, Interval, Alloc>' |
| 288 | # error: implicit conversion loses integer precision: 'int' to 'boost::icl::bound_type' (aka 'unsigned char') | ||
| 289 | target_compile_options(video_core PRIVATE -Wno-shadow -Wno-unused-local-typedef) | ||
| 290 | else() | ||
| 291 | target_compile_options(video_core PRIVATE -Werror=conversion) | ||
| 292 | endif() | ||
| 284 | 293 | ||
| 294 | target_compile_options(video_core PRIVATE | ||
| 285 | -Wno-sign-conversion | 295 | -Wno-sign-conversion |
| 286 | ) | 296 | ) |
| 287 | 297 | ||
| @@ -294,9 +304,13 @@ if (ARCHITECTURE_x86_64) | |||
| 294 | macro/macro_jit_x64.cpp | 304 | macro/macro_jit_x64.cpp |
| 295 | macro/macro_jit_x64.h | 305 | macro/macro_jit_x64.h |
| 296 | ) | 306 | ) |
| 297 | target_link_libraries(video_core PUBLIC xbyak) | 307 | target_link_libraries(video_core PUBLIC xbyak::xbyak) |
| 298 | endif() | 308 | endif() |
| 299 | 309 | ||
| 300 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) | 310 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) |
| 301 | target_link_libraries(video_core PRIVATE dynarmic) | 311 | target_link_libraries(video_core PRIVATE dynarmic::dynarmic) |
| 312 | endif() | ||
| 313 | |||
| 314 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 315 | target_precompile_headers(video_core PRIVATE precompiled_headers.h) | ||
| 302 | endif() | 316 | endif() |
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index f9a6472cf..92d77eef2 100644 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h | |||
| @@ -535,7 +535,7 @@ private: | |||
| 535 | const u64* const state_words = Array<type>(); | 535 | const u64* const state_words = Array<type>(); |
| 536 | const u64 num_query_words = size / BYTES_PER_WORD + 1; | 536 | const u64 num_query_words = size / BYTES_PER_WORD + 1; |
| 537 | const u64 word_begin = offset / BYTES_PER_WORD; | 537 | const u64 word_begin = offset / BYTES_PER_WORD; |
| 538 | const u64 word_end = std::min(word_begin + num_query_words, NumWords()); | 538 | const u64 word_end = std::min<u64>(word_begin + num_query_words, NumWords()); |
| 539 | const u64 page_limit = Common::DivCeil(offset + size, BYTES_PER_PAGE); | 539 | const u64 page_limit = Common::DivCeil(offset + size, BYTES_PER_PAGE); |
| 540 | u64 page_index = (offset / BYTES_PER_PAGE) % PAGES_PER_WORD; | 540 | u64 page_index = (offset / BYTES_PER_PAGE) % PAGES_PER_WORD; |
| 541 | for (u64 word_index = word_begin; word_index < word_end; ++word_index, page_index = 0) { | 541 | for (u64 word_index = word_begin; word_index < word_end; ++word_index, page_index = 0) { |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 5d3a8293b..6881b34c4 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "common/literals.h" | 19 | #include "common/literals.h" |
| 20 | #include "common/lru_cache.h" | 20 | #include "common/lru_cache.h" |
| 21 | #include "common/microprofile.h" | 21 | #include "common/microprofile.h" |
| 22 | #include "common/polyfill_ranges.h" | ||
| 22 | #include "common/settings.h" | 23 | #include "common/settings.h" |
| 23 | #include "core/memory.h" | 24 | #include "core/memory.h" |
| 24 | #include "video_core/buffer_cache/buffer_base.h" | 25 | #include "video_core/buffer_cache/buffer_base.h" |
diff --git a/src/video_core/control/channel_state_cache.h b/src/video_core/control/channel_state_cache.h index 584a0c26c..cdaf4f8d5 100644 --- a/src/video_core/control/channel_state_cache.h +++ b/src/video_core/control/channel_state_cache.h | |||
| @@ -35,8 +35,6 @@ public: | |||
| 35 | explicit ChannelInfo(Tegra::Control::ChannelState& state); | 35 | explicit ChannelInfo(Tegra::Control::ChannelState& state); |
| 36 | ChannelInfo(const ChannelInfo& state) = delete; | 36 | ChannelInfo(const ChannelInfo& state) = delete; |
| 37 | ChannelInfo& operator=(const ChannelInfo&) = delete; | 37 | ChannelInfo& operator=(const ChannelInfo&) = delete; |
| 38 | ChannelInfo(ChannelInfo&& other) = default; | ||
| 39 | ChannelInfo& operator=(ChannelInfo&& other) = default; | ||
| 40 | 38 | ||
| 41 | Tegra::Engines::Maxwell3D& maxwell3d; | 39 | Tegra::Engines::Maxwell3D& maxwell3d; |
| 42 | Tegra::Engines::KeplerCompute& kepler_compute; | 40 | Tegra::Engines::KeplerCompute& kepler_compute; |
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 55462752c..fb9b9b94e 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -126,7 +126,6 @@ void Maxwell3D::InitializeRegisterDefaults() { | |||
| 126 | draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; | 126 | draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true; |
| 127 | draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; | 127 | draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true; |
| 128 | draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; | 128 | draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; |
| 129 | draw_command[MAXWELL3D_REG_INDEX(draw.instance_id)] = true; | ||
| 130 | } | 129 | } |
| 131 | 130 | ||
| 132 | void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { | 131 | void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { |
| @@ -218,16 +217,19 @@ void Maxwell3D::ProcessMethodCall(u32 method, u32 argument, u32 nonshadow_argume | |||
| 218 | regs.index_buffer.count = regs.index_buffer32_first.count; | 217 | regs.index_buffer.count = regs.index_buffer32_first.count; |
| 219 | regs.index_buffer.first = regs.index_buffer32_first.first; | 218 | regs.index_buffer.first = regs.index_buffer32_first.first; |
| 220 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 219 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 220 | draw_indexed = true; | ||
| 221 | return ProcessDraw(); | 221 | return ProcessDraw(); |
| 222 | case MAXWELL3D_REG_INDEX(index_buffer16_first): | 222 | case MAXWELL3D_REG_INDEX(index_buffer16_first): |
| 223 | regs.index_buffer.count = regs.index_buffer16_first.count; | 223 | regs.index_buffer.count = regs.index_buffer16_first.count; |
| 224 | regs.index_buffer.first = regs.index_buffer16_first.first; | 224 | regs.index_buffer.first = regs.index_buffer16_first.first; |
| 225 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 225 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 226 | draw_indexed = true; | ||
| 226 | return ProcessDraw(); | 227 | return ProcessDraw(); |
| 227 | case MAXWELL3D_REG_INDEX(index_buffer8_first): | 228 | case MAXWELL3D_REG_INDEX(index_buffer8_first): |
| 228 | regs.index_buffer.count = regs.index_buffer8_first.count; | 229 | regs.index_buffer.count = regs.index_buffer8_first.count; |
| 229 | regs.index_buffer.first = regs.index_buffer8_first.first; | 230 | regs.index_buffer.first = regs.index_buffer8_first.first; |
| 230 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; | 231 | dirty.flags[VideoCommon::Dirty::IndexBuffer] = true; |
| 232 | draw_indexed = true; | ||
| 231 | return ProcessDraw(); | 233 | return ProcessDraw(); |
| 232 | case MAXWELL3D_REG_INDEX(topology_override): | 234 | case MAXWELL3D_REG_INDEX(topology_override): |
| 233 | use_topology_override = true; | 235 | use_topology_override = true; |
| @@ -300,21 +302,33 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | |||
| 300 | draw_mode = DrawMode::InlineIndex; | 302 | draw_mode = DrawMode::InlineIndex; |
| 301 | }; | 303 | }; |
| 302 | switch (method) { | 304 | switch (method) { |
| 305 | case MAXWELL3D_REG_INDEX(draw.begin): { | ||
| 306 | draw_mode = | ||
| 307 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || | ||
| 308 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) | ||
| 309 | ? DrawMode::Instance | ||
| 310 | : DrawMode::General; | ||
| 311 | break; | ||
| 312 | } | ||
| 303 | case MAXWELL3D_REG_INDEX(draw.end): | 313 | case MAXWELL3D_REG_INDEX(draw.end): |
| 304 | switch (draw_mode) { | 314 | switch (draw_mode) { |
| 305 | case DrawMode::General: | 315 | case DrawMode::General: |
| 306 | ProcessDraw(1); | 316 | ProcessDraw(); |
| 307 | break; | 317 | break; |
| 308 | case DrawMode::InlineIndex: | 318 | case DrawMode::InlineIndex: |
| 309 | regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); | 319 | regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); |
| 310 | regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; | 320 | regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; |
| 311 | ProcessDraw(1); | 321 | draw_indexed = true; |
| 322 | ProcessDraw(); | ||
| 312 | inline_index_draw_indexes.clear(); | 323 | inline_index_draw_indexes.clear(); |
| 313 | break; | 324 | break; |
| 314 | case DrawMode::Instance: | 325 | case DrawMode::Instance: |
| 315 | break; | 326 | break; |
| 316 | } | 327 | } |
| 317 | break; | 328 | break; |
| 329 | case MAXWELL3D_REG_INDEX(index_buffer.count): | ||
| 330 | draw_indexed = true; | ||
| 331 | break; | ||
| 318 | case MAXWELL3D_REG_INDEX(draw_inline_index): | 332 | case MAXWELL3D_REG_INDEX(draw_inline_index): |
| 319 | update_inline_index(method_argument); | 333 | update_inline_index(method_argument); |
| 320 | break; | 334 | break; |
| @@ -328,13 +342,6 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | |||
| 328 | update_inline_index(regs.inline_index_4x8.index2); | 342 | update_inline_index(regs.inline_index_4x8.index2); |
| 329 | update_inline_index(regs.inline_index_4x8.index3); | 343 | update_inline_index(regs.inline_index_4x8.index3); |
| 330 | break; | 344 | break; |
| 331 | case MAXWELL3D_REG_INDEX(draw.instance_id): | ||
| 332 | draw_mode = | ||
| 333 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || | ||
| 334 | (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) | ||
| 335 | ? DrawMode::Instance | ||
| 336 | : DrawMode::General; | ||
| 337 | break; | ||
| 338 | } | 345 | } |
| 339 | } else { | 346 | } else { |
| 340 | ProcessDeferredDraw(); | 347 | ProcessDeferredDraw(); |
| @@ -486,41 +493,51 @@ void Maxwell3D::ProcessQueryGet() { | |||
| 486 | 493 | ||
| 487 | void Maxwell3D::ProcessQueryCondition() { | 494 | void Maxwell3D::ProcessQueryCondition() { |
| 488 | const GPUVAddr condition_address{regs.render_enable.Address()}; | 495 | const GPUVAddr condition_address{regs.render_enable.Address()}; |
| 489 | switch (regs.render_enable.mode) { | 496 | switch (regs.render_enable_override) { |
| 490 | case Regs::RenderEnable::Mode::True: { | 497 | case Regs::RenderEnable::Override::AlwaysRender: |
| 491 | execute_on = true; | 498 | execute_on = true; |
| 492 | break; | 499 | break; |
| 493 | } | 500 | case Regs::RenderEnable::Override::NeverRender: |
| 494 | case Regs::RenderEnable::Mode::False: { | ||
| 495 | execute_on = false; | 501 | execute_on = false; |
| 496 | break; | 502 | break; |
| 497 | } | 503 | case Regs::RenderEnable::Override::UseRenderEnable: |
| 498 | case Regs::RenderEnable::Mode::Conditional: { | 504 | switch (regs.render_enable.mode) { |
| 499 | Regs::ReportSemaphore::Compare cmp; | 505 | case Regs::RenderEnable::Mode::True: { |
| 500 | memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); | 506 | execute_on = true; |
| 501 | execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U; | 507 | break; |
| 502 | break; | 508 | } |
| 503 | } | 509 | case Regs::RenderEnable::Mode::False: { |
| 504 | case Regs::RenderEnable::Mode::IfEqual: { | 510 | execute_on = false; |
| 505 | Regs::ReportSemaphore::Compare cmp; | 511 | break; |
| 506 | memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); | 512 | } |
| 507 | execute_on = | 513 | case Regs::RenderEnable::Mode::Conditional: { |
| 508 | cmp.initial_sequence == cmp.current_sequence && cmp.initial_mode == cmp.current_mode; | 514 | Regs::ReportSemaphore::Compare cmp; |
| 509 | break; | 515 | memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); |
| 510 | } | 516 | execute_on = cmp.initial_sequence != 0U && cmp.initial_mode != 0U; |
| 511 | case Regs::RenderEnable::Mode::IfNotEqual: { | 517 | break; |
| 512 | Regs::ReportSemaphore::Compare cmp; | 518 | } |
| 513 | memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); | 519 | case Regs::RenderEnable::Mode::IfEqual: { |
| 514 | execute_on = | 520 | Regs::ReportSemaphore::Compare cmp; |
| 515 | cmp.initial_sequence != cmp.current_sequence || cmp.initial_mode != cmp.current_mode; | 521 | memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); |
| 516 | break; | 522 | execute_on = cmp.initial_sequence == cmp.current_sequence && |
| 517 | } | 523 | cmp.initial_mode == cmp.current_mode; |
| 518 | default: { | 524 | break; |
| 519 | UNIMPLEMENTED_MSG("Uninplemented Condition Mode!"); | 525 | } |
| 520 | execute_on = true; | 526 | case Regs::RenderEnable::Mode::IfNotEqual: { |
| 527 | Regs::ReportSemaphore::Compare cmp; | ||
| 528 | memory_manager.ReadBlock(condition_address, &cmp, sizeof(cmp)); | ||
| 529 | execute_on = cmp.initial_sequence != cmp.current_sequence || | ||
| 530 | cmp.initial_mode != cmp.current_mode; | ||
| 531 | break; | ||
| 532 | } | ||
| 533 | default: { | ||
| 534 | UNIMPLEMENTED_MSG("Uninplemented Condition Mode!"); | ||
| 535 | execute_on = true; | ||
| 536 | break; | ||
| 537 | } | ||
| 538 | } | ||
| 521 | break; | 539 | break; |
| 522 | } | 540 | } |
| 523 | } | ||
| 524 | } | 541 | } |
| 525 | 542 | ||
| 526 | void Maxwell3D::ProcessCounterReset() { | 543 | void Maxwell3D::ProcessCounterReset() { |
| @@ -624,27 +641,16 @@ void Maxwell3D::ProcessClearBuffers(u32 layer_count) { | |||
| 624 | 641 | ||
| 625 | void Maxwell3D::ProcessDraw(u32 instance_count) { | 642 | void Maxwell3D::ProcessDraw(u32 instance_count) { |
| 626 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), | 643 | LOG_TRACE(HW_GPU, "called, topology={}, count={}", regs.draw.topology.Value(), |
| 627 | regs.vertex_buffer.count); | 644 | draw_indexed ? regs.index_buffer.count : regs.vertex_buffer.count); |
| 628 | |||
| 629 | ASSERT_MSG(!(regs.index_buffer.count && regs.vertex_buffer.count), "Both indexed and direct?"); | ||
| 630 | |||
| 631 | // Both instance configuration registers can not be set at the same time. | ||
| 632 | ASSERT_MSG(regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::First || | ||
| 633 | regs.draw.instance_id != Maxwell3D::Regs::Draw::InstanceId::Unchanged, | ||
| 634 | "Illegal combination of instancing parameters"); | ||
| 635 | 645 | ||
| 636 | ProcessTopologyOverride(); | 646 | ProcessTopologyOverride(); |
| 637 | 647 | ||
| 638 | const bool is_indexed = regs.index_buffer.count && !regs.vertex_buffer.count; | ||
| 639 | if (ShouldExecute()) { | 648 | if (ShouldExecute()) { |
| 640 | rasterizer->Draw(is_indexed, instance_count); | 649 | rasterizer->Draw(draw_indexed, instance_count); |
| 641 | } | 650 | } |
| 642 | 651 | ||
| 643 | if (is_indexed) { | 652 | draw_indexed = false; |
| 644 | regs.index_buffer.count = 0; | 653 | deferred_draw_method.clear(); |
| 645 | } else { | ||
| 646 | regs.vertex_buffer.count = 0; | ||
| 647 | } | ||
| 648 | } | 654 | } |
| 649 | 655 | ||
| 650 | void Maxwell3D::ProcessDeferredDraw() { | 656 | void Maxwell3D::ProcessDeferredDraw() { |
| @@ -667,8 +673,6 @@ void Maxwell3D::ProcessDeferredDraw() { | |||
| 667 | ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?"); | 673 | ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?"); |
| 668 | 674 | ||
| 669 | ProcessDraw(instance_count); | 675 | ProcessDraw(instance_count); |
| 670 | |||
| 671 | deferred_draw_method.clear(); | ||
| 672 | } | 676 | } |
| 673 | 677 | ||
| 674 | } // namespace Tegra::Engines | 678 | } // namespace Tegra::Engines |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index deba292a5..a541cd95f 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -3159,6 +3159,7 @@ private: | |||
| 3159 | std::vector<u32> deferred_draw_method; | 3159 | std::vector<u32> deferred_draw_method; |
| 3160 | enum class DrawMode : u32 { General = 0, Instance, InlineIndex }; | 3160 | enum class DrawMode : u32 { General = 0, Instance, InlineIndex }; |
| 3161 | DrawMode draw_mode{DrawMode::General}; | 3161 | DrawMode draw_mode{DrawMode::General}; |
| 3162 | bool draw_indexed{}; | ||
| 3162 | }; | 3163 | }; |
| 3163 | 3164 | ||
| 3164 | #define ASSERT_REG_POSITION(field_name, position) \ | 3165 | #define ASSERT_REG_POSITION(field_name, position) \ |
diff --git a/src/video_core/engines/sw_blitter/converter.cpp b/src/video_core/engines/sw_blitter/converter.cpp index cd46dfd4f..2419b5632 100644 --- a/src/video_core/engines/sw_blitter/converter.cpp +++ b/src/video_core/engines/sw_blitter/converter.cpp | |||
| @@ -2,12 +2,12 @@ | |||
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include <array> | 4 | #include <array> |
| 5 | #include <bit> | ||
| 6 | #include <cmath> | 5 | #include <cmath> |
| 7 | #include <span> | 6 | #include <span> |
| 8 | #include <unordered_map> | 7 | #include <unordered_map> |
| 9 | 8 | ||
| 10 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/bit_cast.h" | ||
| 11 | #include "video_core/engines/sw_blitter/converter.h" | 11 | #include "video_core/engines/sw_blitter/converter.h" |
| 12 | #include "video_core/surface.h" | 12 | #include "video_core/surface.h" |
| 13 | #include "video_core/textures/decoders.h" | 13 | #include "video_core/textures/decoders.h" |
| @@ -693,21 +693,21 @@ private: | |||
| 693 | return shifted_value >> shift_amount; | 693 | return shifted_value >> shift_amount; |
| 694 | }; | 694 | }; |
| 695 | const auto force_to_fp16 = [](f32 base_value) { | 695 | const auto force_to_fp16 = [](f32 base_value) { |
| 696 | u32 tmp = std::bit_cast<u32>(base_value); | 696 | u32 tmp = Common::BitCast<u32>(base_value); |
| 697 | constexpr size_t fp32_mantissa_bits = 23; | 697 | constexpr size_t fp32_mantissa_bits = 23; |
| 698 | constexpr size_t fp16_mantissa_bits = 10; | 698 | constexpr size_t fp16_mantissa_bits = 10; |
| 699 | constexpr size_t mantissa_mask = | 699 | constexpr size_t mantissa_mask = |
| 700 | ~((1ULL << (fp32_mantissa_bits - fp16_mantissa_bits)) - 1ULL); | 700 | ~((1ULL << (fp32_mantissa_bits - fp16_mantissa_bits)) - 1ULL); |
| 701 | tmp = tmp & static_cast<u32>(mantissa_mask); | 701 | tmp = tmp & static_cast<u32>(mantissa_mask); |
| 702 | // TODO: force the exponent within the range of half float. Not needed in UNORM / SNORM | 702 | // TODO: force the exponent within the range of half float. Not needed in UNORM / SNORM |
| 703 | return std::bit_cast<f32>(tmp); | 703 | return Common::BitCast<f32>(tmp); |
| 704 | }; | 704 | }; |
| 705 | const auto from_fp_n = [&sign_extend](u32 base_value, size_t bits, size_t mantissa) { | 705 | const auto from_fp_n = [&sign_extend](u32 base_value, size_t bits, size_t mantissa) { |
| 706 | constexpr size_t fp32_mantissa_bits = 23; | 706 | constexpr size_t fp32_mantissa_bits = 23; |
| 707 | size_t shift_towards = fp32_mantissa_bits - mantissa; | 707 | size_t shift_towards = fp32_mantissa_bits - mantissa; |
| 708 | const u32 new_value = | 708 | const u32 new_value = |
| 709 | static_cast<u32>(sign_extend(base_value, bits) << shift_towards) & (~(1U << 31)); | 709 | static_cast<u32>(sign_extend(base_value, bits) << shift_towards) & (~(1U << 31)); |
| 710 | return std::bit_cast<f32>(new_value); | 710 | return Common::BitCast<f32>(new_value); |
| 711 | }; | 711 | }; |
| 712 | const auto calculate_snorm = [&]() { | 712 | const auto calculate_snorm = [&]() { |
| 713 | return static_cast<f32>( | 713 | return static_cast<f32>( |
| @@ -737,13 +737,13 @@ private: | |||
| 737 | out_component = force_to_fp16(out_component); | 737 | out_component = force_to_fp16(out_component); |
| 738 | } else if constexpr (component_types[which_component] == ComponentType::FLOAT) { | 738 | } else if constexpr (component_types[which_component] == ComponentType::FLOAT) { |
| 739 | if constexpr (component_sizes[which_component] == 32) { | 739 | if constexpr (component_sizes[which_component] == 32) { |
| 740 | out_component = std::bit_cast<f32>(value); | 740 | out_component = Common::BitCast<f32>(value); |
| 741 | } else if constexpr (component_sizes[which_component] == 16) { | 741 | } else if constexpr (component_sizes[which_component] == 16) { |
| 742 | static constexpr u32 sign_mask = 0x8000; | 742 | static constexpr u32 sign_mask = 0x8000; |
| 743 | static constexpr u32 mantissa_mask = 0x8000; | 743 | static constexpr u32 mantissa_mask = 0x8000; |
| 744 | out_component = std::bit_cast<f32>(((value & sign_mask) << 16) | | 744 | out_component = Common::BitCast<f32>(((value & sign_mask) << 16) | |
| 745 | (((value & 0x7c00) + 0x1C000) << 13) | | 745 | (((value & 0x7c00) + 0x1C000) << 13) | |
| 746 | ((value & mantissa_mask) << 13)); | 746 | ((value & mantissa_mask) << 13)); |
| 747 | } else { | 747 | } else { |
| 748 | out_component = from_fp_n(value, component_sizes[which_component], | 748 | out_component = from_fp_n(value, component_sizes[which_component], |
| 749 | component_sizes[which_component] - 5); | 749 | component_sizes[which_component] - 5); |
| @@ -771,7 +771,7 @@ private: | |||
| 771 | }; | 771 | }; |
| 772 | const auto to_fp_n = [](f32 base_value, size_t bits, size_t mantissa) { | 772 | const auto to_fp_n = [](f32 base_value, size_t bits, size_t mantissa) { |
| 773 | constexpr size_t fp32_mantissa_bits = 23; | 773 | constexpr size_t fp32_mantissa_bits = 23; |
| 774 | u32 tmp_value = std::bit_cast<u32>(std::max(base_value, 0.0f)); | 774 | u32 tmp_value = Common::BitCast<u32>(std::max(base_value, 0.0f)); |
| 775 | size_t shift_towards = fp32_mantissa_bits - mantissa; | 775 | size_t shift_towards = fp32_mantissa_bits - mantissa; |
| 776 | return tmp_value >> shift_towards; | 776 | return tmp_value >> shift_towards; |
| 777 | }; | 777 | }; |
| @@ -799,13 +799,13 @@ private: | |||
| 799 | insert_to_word(tmp_word); | 799 | insert_to_word(tmp_word); |
| 800 | } else if constexpr (component_types[which_component] == ComponentType::FLOAT) { | 800 | } else if constexpr (component_types[which_component] == ComponentType::FLOAT) { |
| 801 | if constexpr (component_sizes[which_component] == 32) { | 801 | if constexpr (component_sizes[which_component] == 32) { |
| 802 | u32 tmp_word = std::bit_cast<u32>(in_component); | 802 | u32 tmp_word = Common::BitCast<u32>(in_component); |
| 803 | insert_to_word(tmp_word); | 803 | insert_to_word(tmp_word); |
| 804 | } else if constexpr (component_sizes[which_component] == 16) { | 804 | } else if constexpr (component_sizes[which_component] == 16) { |
| 805 | static constexpr u32 sign_mask = 0x8000; | 805 | static constexpr u32 sign_mask = 0x8000; |
| 806 | static constexpr u32 mantissa_mask = 0x03ff; | 806 | static constexpr u32 mantissa_mask = 0x03ff; |
| 807 | static constexpr u32 exponent_mask = 0x7c00; | 807 | static constexpr u32 exponent_mask = 0x7c00; |
| 808 | const u32 tmp_word = std::bit_cast<u32>(in_component); | 808 | const u32 tmp_word = Common::BitCast<u32>(in_component); |
| 809 | const u32 half = ((tmp_word >> 16) & sign_mask) | | 809 | const u32 half = ((tmp_word >> 16) & sign_mask) | |
| 810 | ((((tmp_word & 0x7f800000) - 0x38000000) >> 13) & exponent_mask) | | 810 | ((((tmp_word & 0x7f800000) - 0x38000000) >> 13) & exponent_mask) | |
| 811 | ((tmp_word >> 13) & mantissa_mask); | 811 | ((tmp_word >> 13) & mantissa_mask); |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 1bd477011..164a5252a 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
| @@ -125,7 +125,7 @@ u64 ThreadManager::PushCommand(CommandData&& command_data, bool block) { | |||
| 125 | state.queue.Push(CommandDataContainer(std::move(command_data), fence, block)); | 125 | state.queue.Push(CommandDataContainer(std::move(command_data), fence, block)); |
| 126 | 126 | ||
| 127 | if (block) { | 127 | if (block) { |
| 128 | state.cv.wait(lk, thread.get_stop_token(), [this, fence] { | 128 | Common::CondvarWait(state.cv, lk, thread.get_stop_token(), [this, fence] { |
| 129 | return fence <= state.signaled_fence.load(std::memory_order_relaxed); | 129 | return fence <= state.signaled_fence.load(std::memory_order_relaxed); |
| 130 | }); | 130 | }); |
| 131 | } | 131 | } |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 64628d3e3..c71a419c7 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <thread> | 10 | #include <thread> |
| 11 | #include <variant> | 11 | #include <variant> |
| 12 | 12 | ||
| 13 | #include "common/polyfill_thread.h" | ||
| 13 | #include "common/threadsafe_queue.h" | 14 | #include "common/threadsafe_queue.h" |
| 14 | #include "video_core/framebuffer_config.h" | 15 | #include "video_core/framebuffer_config.h" |
| 15 | 16 | ||
diff --git a/src/video_core/precompiled_headers.h b/src/video_core/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/video_core/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index cfd872a40..b6907463c 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | #include <optional> | 7 | #include <optional> |
| 8 | #include <span> | 8 | #include <span> |
| 9 | #include <stop_token> | ||
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/polyfill_thread.h" | ||
| 11 | #include "video_core/engines/fermi_2d.h" | 11 | #include "video_core/engines/fermi_2d.h" |
| 12 | #include "video_core/gpu.h" | 12 | #include "video_core/gpu.h" |
| 13 | 13 | ||
diff --git a/src/video_core/renderer_null/null_rasterizer.cpp b/src/video_core/renderer_null/null_rasterizer.cpp new file mode 100644 index 000000000..9734d84bc --- /dev/null +++ b/src/video_core/renderer_null/null_rasterizer.cpp | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "video_core/host1x/host1x.h" | ||
| 5 | #include "video_core/memory_manager.h" | ||
| 6 | #include "video_core/renderer_null/null_rasterizer.h" | ||
| 7 | |||
| 8 | namespace Null { | ||
| 9 | |||
| 10 | AccelerateDMA::AccelerateDMA() = default; | ||
| 11 | |||
| 12 | bool AccelerateDMA::BufferCopy(GPUVAddr start_address, GPUVAddr end_address, u64 amount) { | ||
| 13 | return true; | ||
| 14 | } | ||
| 15 | bool AccelerateDMA::BufferClear(GPUVAddr src_address, u64 amount, u32 value) { | ||
| 16 | return true; | ||
| 17 | } | ||
| 18 | |||
| 19 | RasterizerNull::RasterizerNull(Core::Memory::Memory& cpu_memory_, Tegra::GPU& gpu) | ||
| 20 | : RasterizerAccelerated(cpu_memory_), m_gpu{gpu} {} | ||
| 21 | RasterizerNull::~RasterizerNull() = default; | ||
| 22 | |||
| 23 | void RasterizerNull::Draw(bool is_indexed, u32 instance_count) {} | ||
| 24 | void RasterizerNull::Clear(u32 layer_count) {} | ||
| 25 | void RasterizerNull::DispatchCompute() {} | ||
| 26 | void RasterizerNull::ResetCounter(VideoCore::QueryType type) {} | ||
| 27 | void RasterizerNull::Query(GPUVAddr gpu_addr, VideoCore::QueryType type, | ||
| 28 | std::optional<u64> timestamp) { | ||
| 29 | if (!gpu_memory) { | ||
| 30 | return; | ||
| 31 | } | ||
| 32 | |||
| 33 | gpu_memory->Write(gpu_addr, u64{0}); | ||
| 34 | if (timestamp) { | ||
| 35 | gpu_memory->Write(gpu_addr + 8, *timestamp); | ||
| 36 | } | ||
| 37 | } | ||
| 38 | void RasterizerNull::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, | ||
| 39 | u32 size) {} | ||
| 40 | void RasterizerNull::DisableGraphicsUniformBuffer(size_t stage, u32 index) {} | ||
| 41 | void RasterizerNull::FlushAll() {} | ||
| 42 | void RasterizerNull::FlushRegion(VAddr addr, u64 size) {} | ||
| 43 | bool RasterizerNull::MustFlushRegion(VAddr addr, u64 size) { | ||
| 44 | return false; | ||
| 45 | } | ||
| 46 | void RasterizerNull::InvalidateRegion(VAddr addr, u64 size) {} | ||
| 47 | void RasterizerNull::OnCPUWrite(VAddr addr, u64 size) {} | ||
| 48 | void RasterizerNull::InvalidateGPUCache() {} | ||
| 49 | void RasterizerNull::UnmapMemory(VAddr addr, u64 size) {} | ||
| 50 | void RasterizerNull::ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) {} | ||
| 51 | void RasterizerNull::SignalFence(std::function<void()>&& func) { | ||
| 52 | func(); | ||
| 53 | } | ||
| 54 | void RasterizerNull::SyncOperation(std::function<void()>&& func) { | ||
| 55 | func(); | ||
| 56 | } | ||
| 57 | void RasterizerNull::SignalSyncPoint(u32 value) { | ||
| 58 | auto& syncpoint_manager = m_gpu.Host1x().GetSyncpointManager(); | ||
| 59 | syncpoint_manager.IncrementGuest(value); | ||
| 60 | syncpoint_manager.IncrementHost(value); | ||
| 61 | } | ||
| 62 | void RasterizerNull::SignalReference() {} | ||
| 63 | void RasterizerNull::ReleaseFences() {} | ||
| 64 | void RasterizerNull::FlushAndInvalidateRegion(VAddr addr, u64 size) {} | ||
| 65 | void RasterizerNull::WaitForIdle() {} | ||
| 66 | void RasterizerNull::FragmentBarrier() {} | ||
| 67 | void RasterizerNull::TiledCacheBarrier() {} | ||
| 68 | void RasterizerNull::FlushCommands() {} | ||
| 69 | void RasterizerNull::TickFrame() {} | ||
| 70 | Tegra::Engines::AccelerateDMAInterface& RasterizerNull::AccessAccelerateDMA() { | ||
| 71 | return m_accelerate_dma; | ||
| 72 | } | ||
| 73 | bool RasterizerNull::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, | ||
| 74 | const Tegra::Engines::Fermi2D::Surface& dst, | ||
| 75 | const Tegra::Engines::Fermi2D::Config& copy_config) { | ||
| 76 | return true; | ||
| 77 | } | ||
| 78 | void RasterizerNull::AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | ||
| 79 | std::span<const u8> memory) {} | ||
| 80 | bool RasterizerNull::AccelerateDisplay(const Tegra::FramebufferConfig& config, | ||
| 81 | VAddr framebuffer_addr, u32 pixel_stride) { | ||
| 82 | return true; | ||
| 83 | } | ||
| 84 | void RasterizerNull::LoadDiskResources(u64 title_id, std::stop_token stop_loading, | ||
| 85 | const VideoCore::DiskResourceLoadCallback& callback) {} | ||
| 86 | void RasterizerNull::InitializeChannel(Tegra::Control::ChannelState& channel) {} | ||
| 87 | void RasterizerNull::BindChannel(Tegra::Control::ChannelState& channel) {} | ||
| 88 | void RasterizerNull::ReleaseChannel(s32 channel_id) {} | ||
| 89 | |||
| 90 | } // namespace Null | ||
diff --git a/src/video_core/renderer_null/null_rasterizer.h b/src/video_core/renderer_null/null_rasterizer.h new file mode 100644 index 000000000..ecf77ba42 --- /dev/null +++ b/src/video_core/renderer_null/null_rasterizer.h | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_types.h" | ||
| 7 | #include "video_core/control/channel_state_cache.h" | ||
| 8 | #include "video_core/engines/maxwell_dma.h" | ||
| 9 | #include "video_core/rasterizer_accelerated.h" | ||
| 10 | #include "video_core/rasterizer_interface.h" | ||
| 11 | |||
| 12 | namespace Core { | ||
| 13 | class System; | ||
| 14 | } | ||
| 15 | |||
| 16 | namespace Null { | ||
| 17 | |||
| 18 | class RasterizerNull; | ||
| 19 | |||
| 20 | class AccelerateDMA : public Tegra::Engines::AccelerateDMAInterface { | ||
| 21 | public: | ||
| 22 | explicit AccelerateDMA(); | ||
| 23 | bool BufferCopy(GPUVAddr start_address, GPUVAddr end_address, u64 amount) override; | ||
| 24 | bool BufferClear(GPUVAddr src_address, u64 amount, u32 value) override; | ||
| 25 | }; | ||
| 26 | |||
| 27 | class RasterizerNull final : public VideoCore::RasterizerAccelerated, | ||
| 28 | protected VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | ||
| 29 | public: | ||
| 30 | explicit RasterizerNull(Core::Memory::Memory& cpu_memory, Tegra::GPU& gpu); | ||
| 31 | ~RasterizerNull() override; | ||
| 32 | |||
| 33 | void Draw(bool is_indexed, u32 instance_count) override; | ||
| 34 | void Clear(u32 layer_count) override; | ||
| 35 | void DispatchCompute() override; | ||
| 36 | void ResetCounter(VideoCore::QueryType type) override; | ||
| 37 | void Query(GPUVAddr gpu_addr, VideoCore::QueryType type, std::optional<u64> timestamp) override; | ||
| 38 | void BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, u32 size) override; | ||
| 39 | void DisableGraphicsUniformBuffer(size_t stage, u32 index) override; | ||
| 40 | void FlushAll() override; | ||
| 41 | void FlushRegion(VAddr addr, u64 size) override; | ||
| 42 | bool MustFlushRegion(VAddr addr, u64 size) override; | ||
| 43 | void InvalidateRegion(VAddr addr, u64 size) override; | ||
| 44 | void OnCPUWrite(VAddr addr, u64 size) override; | ||
| 45 | void InvalidateGPUCache() override; | ||
| 46 | void UnmapMemory(VAddr addr, u64 size) override; | ||
| 47 | void ModifyGPUMemory(size_t as_id, GPUVAddr addr, u64 size) override; | ||
| 48 | void SignalFence(std::function<void()>&& func) override; | ||
| 49 | void SyncOperation(std::function<void()>&& func) override; | ||
| 50 | void SignalSyncPoint(u32 value) override; | ||
| 51 | void SignalReference() override; | ||
| 52 | void ReleaseFences() override; | ||
| 53 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | ||
| 54 | void WaitForIdle() override; | ||
| 55 | void FragmentBarrier() override; | ||
| 56 | void TiledCacheBarrier() override; | ||
| 57 | void FlushCommands() override; | ||
| 58 | void TickFrame() override; | ||
| 59 | bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, | ||
| 60 | const Tegra::Engines::Fermi2D::Surface& dst, | ||
| 61 | const Tegra::Engines::Fermi2D::Config& copy_config) override; | ||
| 62 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | ||
| 63 | void AccelerateInlineToMemory(GPUVAddr address, size_t copy_size, | ||
| 64 | std::span<const u8> memory) override; | ||
| 65 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | ||
| 66 | u32 pixel_stride) override; | ||
| 67 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | ||
| 68 | const VideoCore::DiskResourceLoadCallback& callback) override; | ||
| 69 | void InitializeChannel(Tegra::Control::ChannelState& channel) override; | ||
| 70 | void BindChannel(Tegra::Control::ChannelState& channel) override; | ||
| 71 | void ReleaseChannel(s32 channel_id) override; | ||
| 72 | |||
| 73 | private: | ||
| 74 | Tegra::GPU& m_gpu; | ||
| 75 | AccelerateDMA m_accelerate_dma; | ||
| 76 | }; | ||
| 77 | |||
| 78 | } // namespace Null | ||
diff --git a/src/video_core/renderer_null/renderer_null.cpp b/src/video_core/renderer_null/renderer_null.cpp new file mode 100644 index 000000000..e2a189b63 --- /dev/null +++ b/src/video_core/renderer_null/renderer_null.cpp | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "video_core/renderer_null/renderer_null.h" | ||
| 5 | |||
| 6 | namespace Null { | ||
| 7 | |||
| 8 | RendererNull::RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, | ||
| 9 | Tegra::GPU& gpu, | ||
| 10 | std::unique_ptr<Core::Frontend::GraphicsContext> context_) | ||
| 11 | : RendererBase(emu_window, std::move(context_)), m_gpu(gpu), m_rasterizer(cpu_memory, gpu) {} | ||
| 12 | |||
| 13 | RendererNull::~RendererNull() = default; | ||
| 14 | |||
| 15 | void RendererNull::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | ||
| 16 | if (!framebuffer) { | ||
| 17 | return; | ||
| 18 | } | ||
| 19 | |||
| 20 | m_gpu.RendererFrameEndNotify(); | ||
| 21 | render_window.OnFrameDisplayed(); | ||
| 22 | } | ||
| 23 | |||
| 24 | } // namespace Null | ||
diff --git a/src/video_core/renderer_null/renderer_null.h b/src/video_core/renderer_null/renderer_null.h new file mode 100644 index 000000000..967ff5645 --- /dev/null +++ b/src/video_core/renderer_null/renderer_null.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | #include <string> | ||
| 8 | |||
| 9 | #include "video_core/renderer_base.h" | ||
| 10 | #include "video_core/renderer_null/null_rasterizer.h" | ||
| 11 | |||
| 12 | namespace Null { | ||
| 13 | |||
| 14 | class RendererNull final : public VideoCore::RendererBase { | ||
| 15 | public: | ||
| 16 | explicit RendererNull(Core::Frontend::EmuWindow& emu_window, Core::Memory::Memory& cpu_memory, | ||
| 17 | Tegra::GPU& gpu, | ||
| 18 | std::unique_ptr<Core::Frontend::GraphicsContext> context); | ||
| 19 | ~RendererNull() override; | ||
| 20 | |||
| 21 | void SwapBuffers(const Tegra::FramebufferConfig* framebuffer) override; | ||
| 22 | |||
| 23 | VideoCore::RasterizerInterface* ReadRasterizer() override { | ||
| 24 | return &m_rasterizer; | ||
| 25 | } | ||
| 26 | |||
| 27 | [[nodiscard]] std::string GetDeviceVendor() const override { | ||
| 28 | return "NULL"; | ||
| 29 | } | ||
| 30 | |||
| 31 | private: | ||
| 32 | Tegra::GPU& m_gpu; | ||
| 33 | RasterizerNull m_rasterizer; | ||
| 34 | }; | ||
| 35 | |||
| 36 | } // namespace Null | ||
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 1663e277d..e2e3dac34 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #include "common/literals.h" | 15 | #include "common/literals.h" |
| 16 | #include "common/logging/log.h" | 16 | #include "common/logging/log.h" |
| 17 | #include "common/polyfill_ranges.h" | ||
| 17 | #include "common/settings.h" | 18 | #include "common/settings.h" |
| 18 | #include "shader_recompiler/stage.h" | 19 | #include "shader_recompiler/stage.h" |
| 19 | #include "video_core/renderer_opengl/gl_device.h" | 20 | #include "video_core/renderer_opengl/gl_device.h" |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 3fe04a115..a38060100 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -39,6 +39,7 @@ using Shader::Backend::GLASM::EmitGLASM; | |||
| 39 | using Shader::Backend::GLSL::EmitGLSL; | 39 | using Shader::Backend::GLSL::EmitGLSL; |
| 40 | using Shader::Backend::SPIRV::EmitSPIRV; | 40 | using Shader::Backend::SPIRV::EmitSPIRV; |
| 41 | using Shader::Maxwell::ConvertLegacyToGeneric; | 41 | using Shader::Maxwell::ConvertLegacyToGeneric; |
| 42 | using Shader::Maxwell::GenerateGeometryPassthrough; | ||
| 42 | using Shader::Maxwell::MergeDualVertexPrograms; | 43 | using Shader::Maxwell::MergeDualVertexPrograms; |
| 43 | using Shader::Maxwell::TranslateProgram; | 44 | using Shader::Maxwell::TranslateProgram; |
| 44 | using VideoCommon::ComputeEnvironment; | 45 | using VideoCommon::ComputeEnvironment; |
| @@ -56,6 +57,17 @@ auto MakeSpan(Container& container) { | |||
| 56 | return std::span(container.data(), container.size()); | 57 | return std::span(container.data(), container.size()); |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 60 | Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topology) { | ||
| 61 | switch (topology) { | ||
| 62 | case Maxwell::PrimitiveTopology::Points: | ||
| 63 | return Shader::OutputTopology::PointList; | ||
| 64 | case Maxwell::PrimitiveTopology::LineStrip: | ||
| 65 | return Shader::OutputTopology::LineStrip; | ||
| 66 | default: | ||
| 67 | return Shader::OutputTopology::TriangleStrip; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | |||
| 59 | Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, | 71 | Shader::RuntimeInfo MakeRuntimeInfo(const GraphicsPipelineKey& key, |
| 60 | const Shader::IR::Program& program, | 72 | const Shader::IR::Program& program, |
| 61 | const Shader::IR::Program* previous_program, | 73 | const Shader::IR::Program* previous_program, |
| @@ -220,6 +232,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo | |||
| 220 | .support_int64 = device.HasShaderInt64(), | 232 | .support_int64 = device.HasShaderInt64(), |
| 221 | .needs_demote_reorder = device.IsAmd(), | 233 | .needs_demote_reorder = device.IsAmd(), |
| 222 | .support_snorm_render_buffer = false, | 234 | .support_snorm_render_buffer = false, |
| 235 | .support_viewport_index_layer = device.HasVertexViewportLayer(), | ||
| 223 | } { | 236 | } { |
| 224 | if (use_asynchronous_shaders) { | 237 | if (use_asynchronous_shaders) { |
| 225 | workers = CreateWorkers(); | 238 | workers = CreateWorkers(); |
| @@ -314,9 +327,7 @@ GraphicsPipeline* ShaderCache::CurrentGraphicsPipeline() { | |||
| 314 | const auto& regs{maxwell3d->regs}; | 327 | const auto& regs{maxwell3d->regs}; |
| 315 | graphics_key.raw = 0; | 328 | graphics_key.raw = 0; |
| 316 | graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0); | 329 | graphics_key.early_z.Assign(regs.mandated_early_z != 0 ? 1 : 0); |
| 317 | graphics_key.gs_input_topology.Assign(graphics_key.unique_hashes[4] != 0 | 330 | graphics_key.gs_input_topology.Assign(regs.draw.topology.Value()); |
| 318 | ? regs.draw.topology.Value() | ||
| 319 | : Maxwell::PrimitiveTopology{}); | ||
| 320 | graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value()); | 331 | graphics_key.tessellation_primitive.Assign(regs.tessellation.params.domain_type.Value()); |
| 321 | graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value()); | 332 | graphics_key.tessellation_spacing.Assign(regs.tessellation.params.spacing.Value()); |
| 322 | graphics_key.tessellation_clockwise.Assign( | 333 | graphics_key.tessellation_clockwise.Assign( |
| @@ -415,7 +426,19 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 415 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 426 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| 416 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; | 427 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; |
| 417 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; | 428 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; |
| 429 | |||
| 430 | // Layer passthrough generation for devices without GL_ARB_shader_viewport_layer_array | ||
| 431 | Shader::IR::Program* layer_source_program{}; | ||
| 432 | |||
| 418 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 433 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 434 | const bool is_emulated_stage = layer_source_program != nullptr && | ||
| 435 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 436 | if (key.unique_hashes[index] == 0 && is_emulated_stage) { | ||
| 437 | auto topology = MaxwellToOutputTopology(key.gs_input_topology); | ||
| 438 | programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info, | ||
| 439 | *layer_source_program, topology); | ||
| 440 | continue; | ||
| 441 | } | ||
| 419 | if (key.unique_hashes[index] == 0) { | 442 | if (key.unique_hashes[index] == 0) { |
| 420 | continue; | 443 | continue; |
| 421 | } | 444 | } |
| @@ -443,6 +466,10 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 443 | Shader::NumDescriptors(program_vb.info.storage_buffers_descriptors); | 466 | Shader::NumDescriptors(program_vb.info.storage_buffers_descriptors); |
| 444 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); | 467 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); |
| 445 | } | 468 | } |
| 469 | |||
| 470 | if (programs[index].info.requires_layer_emulation) { | ||
| 471 | layer_source_program = &programs[index]; | ||
| 472 | } | ||
| 446 | } | 473 | } |
| 447 | const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()}; | 474 | const u32 glasm_storage_buffer_limit{device.GetMaxGLASMStorageBufferBlocks()}; |
| 448 | const bool glasm_use_storage_buffers{total_storage_buffers <= glasm_storage_buffer_limit}; | 475 | const bool glasm_use_storage_buffers{total_storage_buffers <= glasm_storage_buffer_limit}; |
| @@ -456,7 +483,9 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 456 | const bool use_glasm{device.UseAssemblyShaders()}; | 483 | const bool use_glasm{device.UseAssemblyShaders()}; |
| 457 | const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0; | 484 | const size_t first_index = uses_vertex_a && uses_vertex_b ? 1 : 0; |
| 458 | for (size_t index = first_index; index < Maxwell::MaxShaderProgram; ++index) { | 485 | for (size_t index = first_index; index < Maxwell::MaxShaderProgram; ++index) { |
| 459 | if (key.unique_hashes[index] == 0) { | 486 | const bool is_emulated_stage = layer_source_program != nullptr && |
| 487 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 488 | if (key.unique_hashes[index] == 0 && !is_emulated_stage) { | ||
| 460 | continue; | 489 | continue; |
| 461 | } | 490 | } |
| 462 | UNIMPLEMENTED_IF(index == 0); | 491 | UNIMPLEMENTED_IF(index == 0); |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 89f181fe3..53ffea904 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <filesystem> | 6 | #include <filesystem> |
| 7 | #include <stop_token> | ||
| 8 | #include <unordered_map> | 7 | #include <unordered_map> |
| 9 | 8 | ||
| 10 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp index 98cc26679..5864e772b 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "common/bit_cast.h" | 7 | #include "common/bit_cast.h" |
| 8 | #include "common/cityhash.h" | 8 | #include "common/cityhash.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" | 11 | #include "video_core/renderer_vulkan/fixed_pipeline_state.h" |
| 11 | #include "video_core/renderer_vulkan/vk_state_tracker.h" | 12 | #include "video_core/renderer_vulkan/vk_state_tracker.h" |
| 12 | 13 | ||
| @@ -92,6 +93,8 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, | |||
| 92 | provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0); | 93 | provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0); |
| 93 | conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0); | 94 | conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0); |
| 94 | smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0); | 95 | smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0); |
| 96 | alpha_to_coverage_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_coverage != 0 ? 1 : 0); | ||
| 97 | alpha_to_one_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_one != 0 ? 1 : 0); | ||
| 95 | 98 | ||
| 96 | for (size_t i = 0; i < regs.rt.size(); ++i) { | 99 | for (size_t i = 0; i < regs.rt.size(); ++i) { |
| 97 | color_formats[i] = static_cast<u8>(regs.rt[i].format); | 100 | color_formats[i] = static_cast<u8>(regs.rt[i].format); |
diff --git a/src/video_core/renderer_vulkan/fixed_pipeline_state.h b/src/video_core/renderer_vulkan/fixed_pipeline_state.h index 1afdef329..ab79fb8f3 100644 --- a/src/video_core/renderer_vulkan/fixed_pipeline_state.h +++ b/src/video_core/renderer_vulkan/fixed_pipeline_state.h | |||
| @@ -195,6 +195,8 @@ struct FixedPipelineState { | |||
| 195 | BitField<12, 1, u32> provoking_vertex_last; | 195 | BitField<12, 1, u32> provoking_vertex_last; |
| 196 | BitField<13, 1, u32> conservative_raster_enable; | 196 | BitField<13, 1, u32> conservative_raster_enable; |
| 197 | BitField<14, 1, u32> smooth_lines; | 197 | BitField<14, 1, u32> smooth_lines; |
| 198 | BitField<15, 1, u32> alpha_to_coverage_enabled; | ||
| 199 | BitField<16, 1, u32> alpha_to_one_enabled; | ||
| 198 | }; | 200 | }; |
| 199 | std::array<u8, Maxwell::NumRenderTargets> color_formats; | 201 | std::array<u8, Maxwell::NumRenderTargets> color_formats; |
| 200 | 202 | ||
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 430a84272..3e03c5cd6 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -58,7 +58,7 @@ VkSamplerAddressMode WrapMode(const Device& device, Tegra::Texture::WrapMode wra | |||
| 58 | case Tegra::Texture::WrapMode::Border: | 58 | case Tegra::Texture::WrapMode::Border: |
| 59 | return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; | 59 | return VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER; |
| 60 | case Tegra::Texture::WrapMode::Clamp: | 60 | case Tegra::Texture::WrapMode::Clamp: |
| 61 | if (device.GetDriverID() == VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR) { | 61 | if (device.GetDriverID() == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { |
| 62 | // Nvidia's Vulkan driver defaults to GL_CLAMP on invalid enumerations, we can hack this | 62 | // Nvidia's Vulkan driver defaults to GL_CLAMP on invalid enumerations, we can hack this |
| 63 | // by sending an invalid enumeration. | 63 | // by sending an invalid enumeration. |
| 64 | return static_cast<VkSamplerAddressMode>(0xcafe); | 64 | return static_cast<VkSamplerAddressMode>(0xcafe); |
diff --git a/src/video_core/renderer_vulkan/pipeline_helper.h b/src/video_core/renderer_vulkan/pipeline_helper.h index b7843e995..28b893e25 100644 --- a/src/video_core/renderer_vulkan/pipeline_helper.h +++ b/src/video_core/renderer_vulkan/pipeline_helper.h | |||
| @@ -44,17 +44,17 @@ public: | |||
| 44 | }); | 44 | }); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | vk::DescriptorUpdateTemplateKHR CreateTemplate(VkDescriptorSetLayout descriptor_set_layout, | 47 | vk::DescriptorUpdateTemplate CreateTemplate(VkDescriptorSetLayout descriptor_set_layout, |
| 48 | VkPipelineLayout pipeline_layout, | 48 | VkPipelineLayout pipeline_layout, |
| 49 | bool use_push_descriptor) const { | 49 | bool use_push_descriptor) const { |
| 50 | if (entries.empty()) { | 50 | if (entries.empty()) { |
| 51 | return nullptr; | 51 | return nullptr; |
| 52 | } | 52 | } |
| 53 | const VkDescriptorUpdateTemplateType type = | 53 | const VkDescriptorUpdateTemplateType type = |
| 54 | use_push_descriptor ? VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR | 54 | use_push_descriptor ? VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR |
| 55 | : VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR; | 55 | : VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET; |
| 56 | return device->GetLogical().CreateDescriptorUpdateTemplateKHR({ | 56 | return device->GetLogical().CreateDescriptorUpdateTemplate({ |
| 57 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, | 57 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, |
| 58 | .pNext = nullptr, | 58 | .pNext = nullptr, |
| 59 | .flags = 0, | 59 | .flags = 0, |
| 60 | .descriptorUpdateEntryCount = static_cast<u32>(entries.size()), | 60 | .descriptorUpdateEntryCount = static_cast<u32>(entries.size()), |
| @@ -129,7 +129,7 @@ private: | |||
| 129 | const Device* device{}; | 129 | const Device* device{}; |
| 130 | bool is_compute{}; | 130 | bool is_compute{}; |
| 131 | boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings; | 131 | boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings; |
| 132 | boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries; | 132 | boost::container::small_vector<VkDescriptorUpdateTemplateEntry, 32> entries; |
| 133 | u32 binding{}; | 133 | u32 binding{}; |
| 134 | u32 num_descriptors{}; | 134 | u32 num_descriptors{}; |
| 135 | size_t offset{}; | 135 | size_t offset{}; |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index c2a95200b..18be54729 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -45,14 +45,14 @@ std::string GetDriverVersion(const Device& device) { | |||
| 45 | // https://github.com/SaschaWillems/vulkan.gpuinfo.org/blob/5dddea46ea1120b0df14eef8f15ff8e318e35462/functions.php#L308-L314 | 45 | // https://github.com/SaschaWillems/vulkan.gpuinfo.org/blob/5dddea46ea1120b0df14eef8f15ff8e318e35462/functions.php#L308-L314 |
| 46 | const u32 version = device.GetDriverVersion(); | 46 | const u32 version = device.GetDriverVersion(); |
| 47 | 47 | ||
| 48 | if (device.GetDriverID() == VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR) { | 48 | if (device.GetDriverID() == VK_DRIVER_ID_NVIDIA_PROPRIETARY) { |
| 49 | const u32 major = (version >> 22) & 0x3ff; | 49 | const u32 major = (version >> 22) & 0x3ff; |
| 50 | const u32 minor = (version >> 14) & 0x0ff; | 50 | const u32 minor = (version >> 14) & 0x0ff; |
| 51 | const u32 secondary = (version >> 6) & 0x0ff; | 51 | const u32 secondary = (version >> 6) & 0x0ff; |
| 52 | const u32 tertiary = version & 0x003f; | 52 | const u32 tertiary = version & 0x003f; |
| 53 | return fmt::format("{}.{}.{}.{}", major, minor, secondary, tertiary); | 53 | return fmt::format("{}.{}.{}.{}", major, minor, secondary, tertiary); |
| 54 | } | 54 | } |
| 55 | if (device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR) { | 55 | if (device.GetDriverID() == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) { |
| 56 | const u32 major = version >> 14; | 56 | const u32 major = version >> 14; |
| 57 | const u32 minor = version & 0x3fff; | 57 | const u32 minor = version & 0x3fff; |
| 58 | return fmt::format("{}.{}", major, minor); | 58 | return fmt::format("{}.{}", major, minor); |
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp index 89426121f..6e5abade4 100644 --- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp +++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "common/assert.h" | 10 | #include "common/assert.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/math_util.h" | 12 | #include "common/math_util.h" |
| 13 | #include "common/polyfill_ranges.h" | ||
| 13 | #include "common/settings.h" | 14 | #include "common/settings.h" |
| 14 | #include "core/core.h" | 15 | #include "core/core.h" |
| 15 | #include "core/frontend/emu_window.h" | 16 | #include "core/frontend/emu_window.h" |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 241d7573e..2c00979d7 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -93,7 +93,7 @@ constexpr DescriptorBankInfo ASTC_BANK_INFO{ | |||
| 93 | .score = 2, | 93 | .score = 2, |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | constexpr VkDescriptorUpdateTemplateEntryKHR INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ | 96 | constexpr VkDescriptorUpdateTemplateEntry INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE{ |
| 97 | .dstBinding = 0, | 97 | .dstBinding = 0, |
| 98 | .dstArrayElement = 0, | 98 | .dstArrayElement = 0, |
| 99 | .descriptorCount = 2, | 99 | .descriptorCount = 2, |
| @@ -102,7 +102,7 @@ constexpr VkDescriptorUpdateTemplateEntryKHR INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMP | |||
| 102 | .stride = sizeof(DescriptorUpdateEntry), | 102 | .stride = sizeof(DescriptorUpdateEntry), |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | constexpr std::array<VkDescriptorUpdateTemplateEntryKHR, ASTC_NUM_BINDINGS> | 105 | constexpr std::array<VkDescriptorUpdateTemplateEntry, ASTC_NUM_BINDINGS> |
| 106 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{ | 106 | ASTC_PASS_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{ |
| 107 | { | 107 | { |
| 108 | .dstBinding = ASTC_BINDING_INPUT_BUFFER, | 108 | .dstBinding = ASTC_BINDING_INPUT_BUFFER, |
| @@ -134,7 +134,7 @@ struct AstcPushConstants { | |||
| 134 | 134 | ||
| 135 | ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, | 135 | ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, |
| 136 | vk::Span<VkDescriptorSetLayoutBinding> bindings, | 136 | vk::Span<VkDescriptorSetLayoutBinding> bindings, |
| 137 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, | 137 | vk::Span<VkDescriptorUpdateTemplateEntry> templates, |
| 138 | const DescriptorBankInfo& bank_info, | 138 | const DescriptorBankInfo& bank_info, |
| 139 | vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code) | 139 | vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code) |
| 140 | : device{device_} { | 140 | : device{device_} { |
| @@ -155,13 +155,13 @@ ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool, | |||
| 155 | .pPushConstantRanges = push_constants.data(), | 155 | .pPushConstantRanges = push_constants.data(), |
| 156 | }); | 156 | }); |
| 157 | if (!templates.empty()) { | 157 | if (!templates.empty()) { |
| 158 | descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplateKHR({ | 158 | descriptor_template = device.GetLogical().CreateDescriptorUpdateTemplate({ |
| 159 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR, | 159 | .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO, |
| 160 | .pNext = nullptr, | 160 | .pNext = nullptr, |
| 161 | .flags = 0, | 161 | .flags = 0, |
| 162 | .descriptorUpdateEntryCount = templates.size(), | 162 | .descriptorUpdateEntryCount = templates.size(), |
| 163 | .pDescriptorUpdateEntries = templates.data(), | 163 | .pDescriptorUpdateEntries = templates.data(), |
| 164 | .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR, | 164 | .templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET, |
| 165 | .descriptorSetLayout = *descriptor_set_layout, | 165 | .descriptorSetLayout = *descriptor_set_layout, |
| 166 | .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, | 166 | .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, |
| 167 | .pipelineLayout = *layout, | 167 | .pipelineLayout = *layout, |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.h b/src/video_core/renderer_vulkan/vk_compute_pass.h index dcc691a8e..5d32e3caf 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.h +++ b/src/video_core/renderer_vulkan/vk_compute_pass.h | |||
| @@ -29,14 +29,14 @@ class ComputePass { | |||
| 29 | public: | 29 | public: |
| 30 | explicit ComputePass(const Device& device, DescriptorPool& descriptor_pool, | 30 | explicit ComputePass(const Device& device, DescriptorPool& descriptor_pool, |
| 31 | vk::Span<VkDescriptorSetLayoutBinding> bindings, | 31 | vk::Span<VkDescriptorSetLayoutBinding> bindings, |
| 32 | vk::Span<VkDescriptorUpdateTemplateEntryKHR> templates, | 32 | vk::Span<VkDescriptorUpdateTemplateEntry> templates, |
| 33 | const DescriptorBankInfo& bank_info, | 33 | const DescriptorBankInfo& bank_info, |
| 34 | vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code); | 34 | vk::Span<VkPushConstantRange> push_constants, std::span<const u32> code); |
| 35 | ~ComputePass(); | 35 | ~ComputePass(); |
| 36 | 36 | ||
| 37 | protected: | 37 | protected: |
| 38 | const Device& device; | 38 | const Device& device; |
| 39 | vk::DescriptorUpdateTemplateKHR descriptor_template; | 39 | vk::DescriptorUpdateTemplate descriptor_template; |
| 40 | vk::PipelineLayout layout; | 40 | vk::PipelineLayout layout; |
| 41 | vk::Pipeline pipeline; | 41 | vk::Pipeline pipeline; |
| 42 | vk::DescriptorSetLayout descriptor_set_layout; | 42 | vk::DescriptorSetLayout descriptor_set_layout; |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 7906e11a8..04a3a861e 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -53,7 +53,7 @@ ComputePipeline::ComputePipeline(const Device& device_, DescriptorPool& descript | |||
| 53 | .requiredSubgroupSize = GuestWarpSize, | 53 | .requiredSubgroupSize = GuestWarpSize, |
| 54 | }; | 54 | }; |
| 55 | VkPipelineCreateFlags flags{}; | 55 | VkPipelineCreateFlags flags{}; |
| 56 | if (device.IsKhrPipelineEexecutablePropertiesEnabled()) { | 56 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { |
| 57 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; | 57 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; |
| 58 | } | 58 | } |
| 59 | pipeline = device.GetLogical().CreateComputePipeline({ | 59 | pipeline = device.GetLogical().CreateComputePipeline({ |
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.h b/src/video_core/renderer_vulkan/vk_compute_pipeline.h index 9879735fe..d70837fc5 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.h | |||
| @@ -55,7 +55,7 @@ private: | |||
| 55 | vk::DescriptorSetLayout descriptor_set_layout; | 55 | vk::DescriptorSetLayout descriptor_set_layout; |
| 56 | DescriptorAllocator descriptor_allocator; | 56 | DescriptorAllocator descriptor_allocator; |
| 57 | vk::PipelineLayout pipeline_layout; | 57 | vk::PipelineLayout pipeline_layout; |
| 58 | vk::DescriptorUpdateTemplateKHR descriptor_update_template; | 58 | vk::DescriptorUpdateTemplate descriptor_update_template; |
| 59 | vk::Pipeline pipeline; | 59 | vk::Pipeline pipeline; |
| 60 | 60 | ||
| 61 | std::condition_variable build_condvar; | 61 | std::condition_variable build_condvar; |
diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index c7196b64e..b5ae6443c 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" | 11 | #include "video_core/renderer_vulkan/vk_descriptor_pool.h" |
| 11 | #include "video_core/renderer_vulkan/vk_resource_pool.h" | 12 | #include "video_core/renderer_vulkan/vk_resource_pool.h" |
| 12 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 13 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index ef75c126c..006128638 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp | |||
| @@ -714,8 +714,8 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 714 | .sampleShadingEnable = VK_FALSE, | 714 | .sampleShadingEnable = VK_FALSE, |
| 715 | .minSampleShading = 0.0f, | 715 | .minSampleShading = 0.0f, |
| 716 | .pSampleMask = nullptr, | 716 | .pSampleMask = nullptr, |
| 717 | .alphaToCoverageEnable = VK_FALSE, | 717 | .alphaToCoverageEnable = key.state.alpha_to_coverage_enabled != 0 ? VK_TRUE : VK_FALSE, |
| 718 | .alphaToOneEnable = VK_FALSE, | 718 | .alphaToOneEnable = key.state.alpha_to_one_enabled != 0 ? VK_TRUE : VK_FALSE, |
| 719 | }; | 719 | }; |
| 720 | const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{ | 720 | const VkPipelineDepthStencilStateCreateInfo depth_stencil_ci{ |
| 721 | .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, | 721 | .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, |
| @@ -830,7 +830,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) { | |||
| 830 | */ | 830 | */ |
| 831 | } | 831 | } |
| 832 | VkPipelineCreateFlags flags{}; | 832 | VkPipelineCreateFlags flags{}; |
| 833 | if (device.IsKhrPipelineEexecutablePropertiesEnabled()) { | 833 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { |
| 834 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; | 834 | flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR; |
| 835 | } | 835 | } |
| 836 | pipeline = device.GetLogical().CreateGraphicsPipeline({ | 836 | pipeline = device.GetLogical().CreateGraphicsPipeline({ |
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index 6bf577d25..1ed2967be 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h | |||
| @@ -151,7 +151,7 @@ private: | |||
| 151 | vk::DescriptorSetLayout descriptor_set_layout; | 151 | vk::DescriptorSetLayout descriptor_set_layout; |
| 152 | DescriptorAllocator descriptor_allocator; | 152 | DescriptorAllocator descriptor_allocator; |
| 153 | vk::PipelineLayout pipeline_layout; | 153 | vk::PipelineLayout pipeline_layout; |
| 154 | vk::DescriptorUpdateTemplateKHR descriptor_update_template; | 154 | vk::DescriptorUpdateTemplate descriptor_update_template; |
| 155 | vk::Pipeline pipeline; | 155 | vk::Pipeline pipeline; |
| 156 | 156 | ||
| 157 | std::condition_variable build_condvar; | 157 | std::condition_variable build_condvar; |
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp index 4e81d3d28..8aa07ef9d 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp | |||
| @@ -11,10 +11,10 @@ | |||
| 11 | namespace Vulkan { | 11 | namespace Vulkan { |
| 12 | 12 | ||
| 13 | MasterSemaphore::MasterSemaphore(const Device& device) { | 13 | MasterSemaphore::MasterSemaphore(const Device& device) { |
| 14 | static constexpr VkSemaphoreTypeCreateInfoKHR semaphore_type_ci{ | 14 | static constexpr VkSemaphoreTypeCreateInfo semaphore_type_ci{ |
| 15 | .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR, | 15 | .sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO, |
| 16 | .pNext = nullptr, | 16 | .pNext = nullptr, |
| 17 | .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE_KHR, | 17 | .semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE, |
| 18 | .initialValue = 0, | 18 | .initialValue = 0, |
| 19 | }; | 19 | }; |
| 20 | static constexpr VkSemaphoreCreateInfo semaphore_ci{ | 20 | static constexpr VkSemaphoreCreateInfo semaphore_ci{ |
| @@ -28,7 +28,7 @@ MasterSemaphore::MasterSemaphore(const Device& device) { | |||
| 28 | return; | 28 | return; |
| 29 | } | 29 | } |
| 30 | // Validation layers have a bug where they fail to track resource usage when using timeline | 30 | // Validation layers have a bug where they fail to track resource usage when using timeline |
| 31 | // semaphores and synchronizing with GetSemaphoreCounterValueKHR. To workaround this issue, have | 31 | // semaphores and synchronizing with GetSemaphoreCounterValue. To workaround this issue, have |
| 32 | // a separate thread waiting for each timeline semaphore value. | 32 | // a separate thread waiting for each timeline semaphore value. |
| 33 | debug_thread = std::jthread([this](std::stop_token stop_token) { | 33 | debug_thread = std::jthread([this](std::stop_token stop_token) { |
| 34 | u64 counter = 0; | 34 | u64 counter = 0; |
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h index 362ed579a..689f02ea5 100644 --- a/src/video_core/renderer_vulkan/vk_master_semaphore.h +++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <thread> | 7 | #include <thread> |
| 8 | 8 | ||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/polyfill_thread.h" | ||
| 10 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 11 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 11 | 12 | ||
| 12 | namespace Vulkan { | 13 | namespace Vulkan { |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index d4b0a542a..38a6b7488 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -46,6 +46,7 @@ MICROPROFILE_DECLARE(Vulkan_PipelineCache); | |||
| 46 | namespace { | 46 | namespace { |
| 47 | using Shader::Backend::SPIRV::EmitSPIRV; | 47 | using Shader::Backend::SPIRV::EmitSPIRV; |
| 48 | using Shader::Maxwell::ConvertLegacyToGeneric; | 48 | using Shader::Maxwell::ConvertLegacyToGeneric; |
| 49 | using Shader::Maxwell::GenerateGeometryPassthrough; | ||
| 49 | using Shader::Maxwell::MergeDualVertexPrograms; | 50 | using Shader::Maxwell::MergeDualVertexPrograms; |
| 50 | using Shader::Maxwell::TranslateProgram; | 51 | using Shader::Maxwell::TranslateProgram; |
| 51 | using VideoCommon::ComputeEnvironment; | 52 | using VideoCommon::ComputeEnvironment; |
| @@ -53,13 +54,24 @@ using VideoCommon::FileEnvironment; | |||
| 53 | using VideoCommon::GenericEnvironment; | 54 | using VideoCommon::GenericEnvironment; |
| 54 | using VideoCommon::GraphicsEnvironment; | 55 | using VideoCommon::GraphicsEnvironment; |
| 55 | 56 | ||
| 56 | constexpr u32 CACHE_VERSION = 7; | 57 | constexpr u32 CACHE_VERSION = 8; |
| 57 | 58 | ||
| 58 | template <typename Container> | 59 | template <typename Container> |
| 59 | auto MakeSpan(Container& container) { | 60 | auto MakeSpan(Container& container) { |
| 60 | return std::span(container.data(), container.size()); | 61 | return std::span(container.data(), container.size()); |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 64 | Shader::OutputTopology MaxwellToOutputTopology(Maxwell::PrimitiveTopology topology) { | ||
| 65 | switch (topology) { | ||
| 66 | case Maxwell::PrimitiveTopology::Points: | ||
| 67 | return Shader::OutputTopology::PointList; | ||
| 68 | case Maxwell::PrimitiveTopology::LineStrip: | ||
| 69 | return Shader::OutputTopology::LineStrip; | ||
| 70 | default: | ||
| 71 | return Shader::OutputTopology::TriangleStrip; | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 63 | Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) { | 75 | Shader::CompareFunction MaxwellToCompareFunction(Maxwell::ComparisonOp comparison) { |
| 64 | switch (comparison) { | 76 | switch (comparison) { |
| 65 | case Maxwell::ComparisonOp::Never_D3D: | 77 | case Maxwell::ComparisonOp::Never_D3D: |
| @@ -275,9 +287,9 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 275 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), | 287 | workers(std::max(std::thread::hardware_concurrency(), 2U) - 1, "VkPipelineBuilder"), |
| 276 | serialization_thread(1, "VkPipelineSerialization") { | 288 | serialization_thread(1, "VkPipelineSerialization") { |
| 277 | const auto& float_control{device.FloatControlProperties()}; | 289 | const auto& float_control{device.FloatControlProperties()}; |
| 278 | const VkDriverIdKHR driver_id{device.GetDriverID()}; | 290 | const VkDriverId driver_id{device.GetDriverID()}; |
| 279 | profile = Shader::Profile{ | 291 | profile = Shader::Profile{ |
| 280 | .supported_spirv = device.IsKhrSpirv1_4Supported() ? 0x00010400U : 0x00010000U, | 292 | .supported_spirv = device.SupportedSpirvVersion(), |
| 281 | .unified_descriptor_binding = true, | 293 | .unified_descriptor_binding = true, |
| 282 | .support_descriptor_aliasing = true, | 294 | .support_descriptor_aliasing = true, |
| 283 | .support_int8 = device.IsInt8Supported(), | 295 | .support_int8 = device.IsInt8Supported(), |
| @@ -285,10 +297,10 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 285 | .support_int64 = device.IsShaderInt64Supported(), | 297 | .support_int64 = device.IsShaderInt64Supported(), |
| 286 | .support_vertex_instance_id = false, | 298 | .support_vertex_instance_id = false, |
| 287 | .support_float_controls = true, | 299 | .support_float_controls = true, |
| 288 | .support_separate_denorm_behavior = float_control.denormBehaviorIndependence == | 300 | .support_separate_denorm_behavior = |
| 289 | VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR, | 301 | float_control.denormBehaviorIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, |
| 290 | .support_separate_rounding_mode = | 302 | .support_separate_rounding_mode = |
| 291 | float_control.roundingModeIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR, | 303 | float_control.roundingModeIndependence == VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL, |
| 292 | .support_fp16_denorm_preserve = float_control.shaderDenormPreserveFloat16 != VK_FALSE, | 304 | .support_fp16_denorm_preserve = float_control.shaderDenormPreserveFloat16 != VK_FALSE, |
| 293 | .support_fp32_denorm_preserve = float_control.shaderDenormPreserveFloat32 != VK_FALSE, | 305 | .support_fp32_denorm_preserve = float_control.shaderDenormPreserveFloat32 != VK_FALSE, |
| 294 | .support_fp16_denorm_flush = float_control.shaderDenormFlushToZeroFloat16 != VK_FALSE, | 306 | .support_fp16_denorm_flush = float_control.shaderDenormFlushToZeroFloat16 != VK_FALSE, |
| @@ -315,18 +327,19 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device | |||
| 315 | .lower_left_origin_mode = false, | 327 | .lower_left_origin_mode = false, |
| 316 | .need_declared_frag_colors = false, | 328 | .need_declared_frag_colors = false, |
| 317 | 329 | ||
| 318 | .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR, | 330 | .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS, |
| 319 | .has_broken_unsigned_image_offsets = false, | 331 | .has_broken_unsigned_image_offsets = false, |
| 320 | .has_broken_signed_operations = false, | 332 | .has_broken_signed_operations = false, |
| 321 | .has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, | 333 | .has_broken_fp16_float_controls = driver_id == VK_DRIVER_ID_NVIDIA_PROPRIETARY, |
| 322 | .ignore_nan_fp_comparisons = false, | 334 | .ignore_nan_fp_comparisons = false, |
| 323 | }; | 335 | }; |
| 324 | host_info = Shader::HostTranslateInfo{ | 336 | host_info = Shader::HostTranslateInfo{ |
| 325 | .support_float16 = device.IsFloat16Supported(), | 337 | .support_float16 = device.IsFloat16Supported(), |
| 326 | .support_int64 = device.IsShaderInt64Supported(), | 338 | .support_int64 = device.IsShaderInt64Supported(), |
| 327 | .needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR || | 339 | .needs_demote_reorder = |
| 328 | driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR, | 340 | driver_id == VK_DRIVER_ID_AMD_PROPRIETARY || driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE, |
| 329 | .support_snorm_render_buffer = true, | 341 | .support_snorm_render_buffer = true, |
| 342 | .support_viewport_index_layer = device.IsExtShaderViewportIndexLayerSupported(), | ||
| 330 | }; | 343 | }; |
| 331 | } | 344 | } |
| 332 | 345 | ||
| @@ -395,7 +408,7 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading | |||
| 395 | std::unique_ptr<PipelineStatistics> statistics; | 408 | std::unique_ptr<PipelineStatistics> statistics; |
| 396 | } state; | 409 | } state; |
| 397 | 410 | ||
| 398 | if (device.IsKhrPipelineEexecutablePropertiesEnabled()) { | 411 | if (device.IsKhrPipelineExecutablePropertiesEnabled()) { |
| 399 | state.statistics = std::make_unique<PipelineStatistics>(device); | 412 | state.statistics = std::make_unique<PipelineStatistics>(device); |
| 400 | } | 413 | } |
| 401 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { | 414 | const auto load_compute{[&](std::ifstream& file, FileEnvironment env) { |
| @@ -509,7 +522,19 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 509 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; | 522 | std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; |
| 510 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; | 523 | const bool uses_vertex_a{key.unique_hashes[0] != 0}; |
| 511 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; | 524 | const bool uses_vertex_b{key.unique_hashes[1] != 0}; |
| 525 | |||
| 526 | // Layer passthrough generation for devices without VK_EXT_shader_viewport_index_layer | ||
| 527 | Shader::IR::Program* layer_source_program{}; | ||
| 528 | |||
| 512 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 529 | for (size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 530 | const bool is_emulated_stage = layer_source_program != nullptr && | ||
| 531 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 532 | if (key.unique_hashes[index] == 0 && is_emulated_stage) { | ||
| 533 | auto topology = MaxwellToOutputTopology(key.state.topology); | ||
| 534 | programs[index] = GenerateGeometryPassthrough(pools.inst, pools.block, host_info, | ||
| 535 | *layer_source_program, topology); | ||
| 536 | continue; | ||
| 537 | } | ||
| 513 | if (key.unique_hashes[index] == 0) { | 538 | if (key.unique_hashes[index] == 0) { |
| 514 | continue; | 539 | continue; |
| 515 | } | 540 | } |
| @@ -530,6 +555,10 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 530 | auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; | 555 | auto program_vb{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; |
| 531 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); | 556 | programs[index] = MergeDualVertexPrograms(program_va, program_vb, env); |
| 532 | } | 557 | } |
| 558 | |||
| 559 | if (programs[index].info.requires_layer_emulation) { | ||
| 560 | layer_source_program = &programs[index]; | ||
| 561 | } | ||
| 533 | } | 562 | } |
| 534 | std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{}; | 563 | std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{}; |
| 535 | std::array<vk::ShaderModule, Maxwell::MaxShaderStage> modules; | 564 | std::array<vk::ShaderModule, Maxwell::MaxShaderStage> modules; |
| @@ -538,7 +567,9 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( | |||
| 538 | Shader::Backend::Bindings binding; | 567 | Shader::Backend::Bindings binding; |
| 539 | for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram; | 568 | for (size_t index = uses_vertex_a && uses_vertex_b ? 1 : 0; index < Maxwell::MaxShaderProgram; |
| 540 | ++index) { | 569 | ++index) { |
| 541 | if (key.unique_hashes[index] == 0) { | 570 | const bool is_emulated_stage = layer_source_program != nullptr && |
| 571 | index == static_cast<u32>(Maxwell::ShaderType::Geometry); | ||
| 572 | if (key.unique_hashes[index] == 0 && !is_emulated_stage) { | ||
| 542 | continue; | 573 | continue; |
| 543 | } | 574 | } |
| 544 | UNIMPLEMENTED_IF(index == 0); | 575 | UNIMPLEMENTED_IF(index == 0); |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 4b15c0f85..929c8ece6 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp | |||
| @@ -98,7 +98,7 @@ HostCounter::HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> depend | |||
| 98 | query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} { | 98 | query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} { |
| 99 | const vk::Device* logical = &cache.GetDevice().GetLogical(); | 99 | const vk::Device* logical = &cache.GetDevice().GetLogical(); |
| 100 | cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) { | 100 | cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) { |
| 101 | logical->ResetQueryPoolEXT(query.first, query.second, 1); | 101 | logical->ResetQueryPool(query.first, query.second, 1); |
| 102 | cmdbuf.BeginQuery(query.first, query.second, VK_QUERY_CONTROL_PRECISE_BIT); | 102 | cmdbuf.BeginQuery(query.first, query.second, VK_QUERY_CONTROL_PRECISE_BIT); |
| 103 | }); | 103 | }); |
| 104 | } | 104 | } |
diff --git a/src/video_core/renderer_vulkan/vk_render_pass_cache.h b/src/video_core/renderer_vulkan/vk_render_pass_cache.h index dc21b7e69..91ad4bf57 100644 --- a/src/video_core/renderer_vulkan/vk_render_pass_cache.h +++ b/src/video_core/renderer_vulkan/vk_render_pass_cache.h | |||
| @@ -12,7 +12,7 @@ | |||
| 12 | namespace Vulkan { | 12 | namespace Vulkan { |
| 13 | 13 | ||
| 14 | struct RenderPassKey { | 14 | struct RenderPassKey { |
| 15 | auto operator<=>(const RenderPassKey&) const noexcept = default; | 15 | bool operator==(const RenderPassKey&) const noexcept = default; |
| 16 | 16 | ||
| 17 | std::array<VideoCore::Surface::PixelFormat, 8> color_formats; | 17 | std::array<VideoCore::Surface::PixelFormat, 8> color_formats; |
| 18 | VideoCore::Surface::PixelFormat depth_format; | 18 | VideoCore::Surface::PixelFormat depth_format; |
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index 4a7b633b7..c2e53a5d5 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp | |||
| @@ -145,7 +145,7 @@ void Scheduler::WorkerThread(std::stop_token stop_token) { | |||
| 145 | if (work_queue.empty()) { | 145 | if (work_queue.empty()) { |
| 146 | wait_cv.notify_all(); | 146 | wait_cv.notify_all(); |
| 147 | } | 147 | } |
| 148 | work_cv.wait(lock, stop_token, [this] { return !work_queue.empty(); }); | 148 | Common::CondvarWait(work_cv, lock, stop_token, [&] { return !work_queue.empty(); }); |
| 149 | if (stop_token.stop_requested()) { | 149 | if (stop_token.stop_requested()) { |
| 150 | continue; | 150 | continue; |
| 151 | } | 151 | } |
| @@ -194,8 +194,8 @@ void Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_s | |||
| 194 | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, | 194 | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, |
| 195 | }; | 195 | }; |
| 196 | 196 | ||
| 197 | const VkTimelineSemaphoreSubmitInfoKHR timeline_si{ | 197 | const VkTimelineSemaphoreSubmitInfo timeline_si{ |
| 198 | .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR, | 198 | .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO, |
| 199 | .pNext = nullptr, | 199 | .pNext = nullptr, |
| 200 | .waitSemaphoreValueCount = num_wait_semaphores, | 200 | .waitSemaphoreValueCount = num_wait_semaphores, |
| 201 | .pWaitSemaphoreValues = wait_values.data(), | 201 | .pWaitSemaphoreValues = wait_values.data(), |
diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index 929216749..3858c506c 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/alignment.h" | 13 | #include "common/alignment.h" |
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/polyfill_thread.h" | ||
| 15 | #include "video_core/renderer_vulkan/vk_master_semaphore.h" | 16 | #include "video_core/renderer_vulkan/vk_master_semaphore.h" |
| 16 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 17 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 17 | 18 | ||
diff --git a/src/video_core/renderer_vulkan/vk_swapchain.cpp b/src/video_core/renderer_vulkan/vk_swapchain.cpp index 706d9ba74..d7be417f5 100644 --- a/src/video_core/renderer_vulkan/vk_swapchain.cpp +++ b/src/video_core/renderer_vulkan/vk_swapchain.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <vector> | 7 | #include <vector> |
| 8 | 8 | ||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "common/settings.h" | 11 | #include "common/settings.h" |
| 11 | #include "core/core.h" | 12 | #include "core/core.h" |
| 12 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 13 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h index a4391202d..f3cc4c70b 100644 --- a/src/video_core/shader_cache.h +++ b/src/video_core/shader_cache.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <vector> | 12 | #include <vector> |
| 13 | 13 | ||
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/polyfill_ranges.h" | ||
| 15 | #include "video_core/control/channel_state_cache.h" | 16 | #include "video_core/control/channel_state_cache.h" |
| 16 | #include "video_core/rasterizer_interface.h" | 17 | #include "video_core/rasterizer_interface.h" |
| 17 | #include "video_core/shader_environment.h" | 18 | #include "video_core/shader_environment.h" |
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index f24f320b6..958810747 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include "common/fs/fs.h" | 15 | #include "common/fs/fs.h" |
| 16 | #include "common/fs/path_util.h" | 16 | #include "common/fs/path_util.h" |
| 17 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 18 | #include "common/polyfill_ranges.h" | ||
| 18 | #include "shader_recompiler/environment.h" | 19 | #include "shader_recompiler/environment.h" |
| 19 | #include "video_core/engines/kepler_compute.h" | 20 | #include "video_core/engines/kepler_compute.h" |
| 20 | #include "video_core/memory_manager.h" | 21 | #include "video_core/memory_manager.h" |
diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index bb55b029f..1342fab1e 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h | |||
| @@ -10,12 +10,12 @@ | |||
| 10 | #include <memory> | 10 | #include <memory> |
| 11 | #include <optional> | 11 | #include <optional> |
| 12 | #include <span> | 12 | #include <span> |
| 13 | #include <stop_token> | ||
| 14 | #include <type_traits> | 13 | #include <type_traits> |
| 15 | #include <unordered_map> | 14 | #include <unordered_map> |
| 16 | #include <vector> | 15 | #include <vector> |
| 17 | 16 | ||
| 18 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "common/polyfill_thread.h" | ||
| 19 | #include "common/unique_function.h" | 19 | #include "common/unique_function.h" |
| 20 | #include "shader_recompiler/environment.h" | 20 | #include "shader_recompiler/environment.h" |
| 21 | #include "video_core/engines/maxwell_3d.h" | 21 | #include "video_core/engines/maxwell_3d.h" |
diff --git a/src/video_core/texture_cache/formatter.cpp b/src/video_core/texture_cache/formatter.cpp index ee4f2d406..418890126 100644 --- a/src/video_core/texture_cache/formatter.cpp +++ b/src/video_core/texture_cache/formatter.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | #include <string> | 5 | #include <string> |
| 6 | 6 | ||
| 7 | #include "common/polyfill_ranges.h" | ||
| 7 | #include "video_core/texture_cache/formatter.h" | 8 | #include "video_core/texture_cache/formatter.h" |
| 8 | #include "video_core/texture_cache/image_base.h" | 9 | #include "video_core/texture_cache/image_base.h" |
| 9 | #include "video_core/texture_cache/image_info.h" | 10 | #include "video_core/texture_cache/image_info.h" |
diff --git a/src/video_core/texture_cache/render_targets.h b/src/video_core/texture_cache/render_targets.h index 1efbd6507..0829d773a 100644 --- a/src/video_core/texture_cache/render_targets.h +++ b/src/video_core/texture_cache/render_targets.h | |||
| @@ -13,7 +13,7 @@ namespace VideoCommon { | |||
| 13 | 13 | ||
| 14 | /// Framebuffer properties used to lookup a framebuffer | 14 | /// Framebuffer properties used to lookup a framebuffer |
| 15 | struct RenderTargets { | 15 | struct RenderTargets { |
| 16 | constexpr auto operator<=>(const RenderTargets&) const noexcept = default; | 16 | constexpr bool operator==(const RenderTargets&) const noexcept = default; |
| 17 | 17 | ||
| 18 | constexpr bool Contains(std::span<const ImageViewId> elements) const noexcept { | 18 | constexpr bool Contains(std::span<const ImageViewId> elements) const noexcept { |
| 19 | const auto contains = [elements](ImageViewId item) { | 19 | const auto contains = [elements](ImageViewId item) { |
diff --git a/src/video_core/texture_cache/slot_vector.h b/src/video_core/texture_cache/slot_vector.h index 46e8a86e6..1e2aad76a 100644 --- a/src/video_core/texture_cache/slot_vector.h +++ b/src/video_core/texture_cache/slot_vector.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/assert.h" | 13 | #include "common/assert.h" |
| 14 | #include "common/common_types.h" | 14 | #include "common/common_types.h" |
| 15 | #include "common/polyfill_ranges.h" | ||
| 15 | 16 | ||
| 16 | namespace VideoCommon { | 17 | namespace VideoCommon { |
| 17 | 18 | ||
diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index 9db7195bf..587339a31 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include "common/hash.h" | 16 | #include "common/hash.h" |
| 17 | #include "common/literals.h" | 17 | #include "common/literals.h" |
| 18 | #include "common/lru_cache.h" | 18 | #include "common/lru_cache.h" |
| 19 | #include "common/polyfill_ranges.h" | ||
| 19 | #include "video_core/compatible_formats.h" | 20 | #include "video_core/compatible_formats.h" |
| 20 | #include "video_core/control/channel_state_cache.h" | 21 | #include "video_core/control/channel_state_cache.h" |
| 21 | #include "video_core/delayed_destruction_ring.h" | 22 | #include "video_core/delayed_destruction_ring.h" |
| @@ -60,8 +61,6 @@ public: | |||
| 60 | TextureCacheChannelInfo(Tegra::Control::ChannelState& state) noexcept; | 61 | TextureCacheChannelInfo(Tegra::Control::ChannelState& state) noexcept; |
| 61 | TextureCacheChannelInfo(const TextureCacheChannelInfo& state) = delete; | 62 | TextureCacheChannelInfo(const TextureCacheChannelInfo& state) = delete; |
| 62 | TextureCacheChannelInfo& operator=(const TextureCacheChannelInfo&) = delete; | 63 | TextureCacheChannelInfo& operator=(const TextureCacheChannelInfo&) = delete; |
| 63 | TextureCacheChannelInfo(TextureCacheChannelInfo&& other) noexcept = default; | ||
| 64 | TextureCacheChannelInfo& operator=(TextureCacheChannelInfo&& other) noexcept = default; | ||
| 65 | 64 | ||
| 66 | DescriptorTable<TICEntry> graphics_image_table{gpu_memory}; | 65 | DescriptorTable<TICEntry> graphics_image_table{gpu_memory}; |
| 67 | DescriptorTable<TSCEntry> graphics_sampler_table{gpu_memory}; | 66 | DescriptorTable<TSCEntry> graphics_sampler_table{gpu_memory}; |
diff --git a/src/video_core/textures/astc.cpp b/src/video_core/textures/astc.cpp index 69a32819a..e8d7c7863 100644 --- a/src/video_core/textures/astc.cpp +++ b/src/video_core/textures/astc.cpp | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include "common/alignment.h" | 16 | #include "common/alignment.h" |
| 17 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "common/polyfill_ranges.h" | ||
| 18 | #include "common/thread_worker.h" | 19 | #include "common/thread_worker.h" |
| 19 | #include "video_core/textures/astc.h" | 20 | #include "video_core/textures/astc.h" |
| 20 | 21 | ||
diff --git a/src/video_core/transform_feedback.cpp b/src/video_core/transform_feedback.cpp index 45071185a..155599316 100644 --- a/src/video_core/transform_feedback.cpp +++ b/src/video_core/transform_feedback.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #include "common/alignment.h" | 8 | #include "common/alignment.h" |
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/polyfill_ranges.h" | ||
| 10 | #include "shader_recompiler/shader_info.h" | 11 | #include "shader_recompiler/shader_info.h" |
| 11 | #include "video_core/transform_feedback.h" | 12 | #include "video_core/transform_feedback.h" |
| 12 | 13 | ||
diff --git a/src/video_core/video_core.cpp b/src/video_core/video_core.cpp index 04ac4af11..fedb4a7bb 100644 --- a/src/video_core/video_core.cpp +++ b/src/video_core/video_core.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include "common/settings.h" | 7 | #include "common/settings.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "video_core/renderer_base.h" | 9 | #include "video_core/renderer_base.h" |
| 10 | #include "video_core/renderer_null/renderer_null.h" | ||
| 10 | #include "video_core/renderer_opengl/renderer_opengl.h" | 11 | #include "video_core/renderer_opengl/renderer_opengl.h" |
| 11 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 12 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| 12 | #include "video_core/video_core.h" | 13 | #include "video_core/video_core.h" |
| @@ -26,6 +27,9 @@ std::unique_ptr<VideoCore::RendererBase> CreateRenderer( | |||
| 26 | case Settings::RendererBackend::Vulkan: | 27 | case Settings::RendererBackend::Vulkan: |
| 27 | return std::make_unique<Vulkan::RendererVulkan>(telemetry_session, emu_window, cpu_memory, | 28 | return std::make_unique<Vulkan::RendererVulkan>(telemetry_session, emu_window, cpu_memory, |
| 28 | gpu, std::move(context)); | 29 | gpu, std::move(context)); |
| 30 | case Settings::RendererBackend::Null: | ||
| 31 | return std::make_unique<Null::RendererNull>(emu_window, cpu_memory, gpu, | ||
| 32 | std::move(context)); | ||
| 29 | default: | 33 | default: |
| 30 | return nullptr; | 34 | return nullptr; |
| 31 | } | 35 | } |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index cdda06813..6a2ad4b1d 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | #include "common/assert.h" | 13 | #include "common/assert.h" |
| 14 | #include "common/literals.h" | 14 | #include "common/literals.h" |
| 15 | #include "common/polyfill_ranges.h" | ||
| 15 | #include "common/settings.h" | 16 | #include "common/settings.h" |
| 16 | #include "video_core/vulkan_common/nsight_aftermath_tracker.h" | 17 | #include "video_core/vulkan_common/nsight_aftermath_tracker.h" |
| 17 | #include "video_core/vulkan_common/vulkan_device.h" | 18 | #include "video_core/vulkan_common/vulkan_device.h" |
| @@ -74,23 +75,8 @@ enum class NvidiaArchitecture { | |||
| 74 | }; | 75 | }; |
| 75 | 76 | ||
| 76 | constexpr std::array REQUIRED_EXTENSIONS{ | 77 | constexpr std::array REQUIRED_EXTENSIONS{ |
| 77 | VK_KHR_MAINTENANCE1_EXTENSION_NAME, | ||
| 78 | VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME, | ||
| 79 | VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, | ||
| 80 | VK_KHR_16BIT_STORAGE_EXTENSION_NAME, | ||
| 81 | VK_KHR_8BIT_STORAGE_EXTENSION_NAME, | ||
| 82 | VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, | ||
| 83 | VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, | ||
| 84 | VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, | ||
| 85 | VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, | ||
| 86 | VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, | ||
| 87 | VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME, | ||
| 88 | VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, | 78 | VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, |
| 89 | VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME, | ||
| 90 | VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME, | ||
| 91 | VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, | 79 | VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, |
| 92 | VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, | ||
| 93 | VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME, | ||
| 94 | #ifdef _WIN32 | 80 | #ifdef _WIN32 |
| 95 | VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, | 81 | VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME, |
| 96 | #endif | 82 | #endif |
| @@ -99,6 +85,19 @@ constexpr std::array REQUIRED_EXTENSIONS{ | |||
| 99 | #endif | 85 | #endif |
| 100 | }; | 86 | }; |
| 101 | 87 | ||
| 88 | constexpr std::array REQUIRED_EXTENSIONS_BEFORE_1_2{ | ||
| 89 | VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME, | ||
| 90 | VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, | ||
| 91 | VK_KHR_8BIT_STORAGE_EXTENSION_NAME, | ||
| 92 | VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME, | ||
| 93 | VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME, | ||
| 94 | VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, | ||
| 95 | }; | ||
| 96 | |||
| 97 | constexpr std::array REQUIRED_EXTENSIONS_BEFORE_1_3{ | ||
| 98 | VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME, | ||
| 99 | }; | ||
| 100 | |||
| 102 | template <typename T> | 101 | template <typename T> |
| 103 | void SetNext(void**& next, T& data) { | 102 | void SetNext(void**& next, T& data) { |
| 104 | *next = &data; | 103 | *next = &data; |
| @@ -308,10 +307,10 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, | |||
| 308 | VkPhysicalDeviceFragmentShadingRatePropertiesKHR shading_rate_props{}; | 307 | VkPhysicalDeviceFragmentShadingRatePropertiesKHR shading_rate_props{}; |
| 309 | shading_rate_props.sType = | 308 | shading_rate_props.sType = |
| 310 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR; | 309 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR; |
| 311 | VkPhysicalDeviceProperties2KHR physical_properties{}; | 310 | VkPhysicalDeviceProperties2 physical_properties{}; |
| 312 | physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; | 311 | physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; |
| 313 | physical_properties.pNext = &shading_rate_props; | 312 | physical_properties.pNext = &shading_rate_props; |
| 314 | physical.GetProperties2KHR(physical_properties); | 313 | physical.GetProperties2(physical_properties); |
| 315 | if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) { | 314 | if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) { |
| 316 | // Only Ampere and newer support this feature | 315 | // Only Ampere and newer support this feature |
| 317 | return NvidiaArchitecture::AmpereOrNewer; | 316 | return NvidiaArchitecture::AmpereOrNewer; |
| @@ -327,7 +326,8 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical, | |||
| 327 | Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface, | 326 | Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface, |
| 328 | const vk::InstanceDispatch& dld_) | 327 | const vk::InstanceDispatch& dld_) |
| 329 | : instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()}, | 328 | : instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()}, |
| 330 | supported_extensions{GetSupportedExtensions(physical)}, | 329 | instance_version{properties.apiVersion}, supported_extensions{GetSupportedExtensions( |
| 330 | physical)}, | ||
| 331 | format_properties(GetFormatProperties(physical)) { | 331 | format_properties(GetFormatProperties(physical)) { |
| 332 | CheckSuitability(surface != nullptr); | 332 | CheckSuitability(surface != nullptr); |
| 333 | SetupFamilies(surface); | 333 | SetupFamilies(surface); |
| @@ -401,15 +401,15 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 401 | const void* first_next = &features2; | 401 | const void* first_next = &features2; |
| 402 | void** next = &features2.pNext; | 402 | void** next = &features2.pNext; |
| 403 | 403 | ||
| 404 | VkPhysicalDeviceTimelineSemaphoreFeaturesKHR timeline_semaphore{ | 404 | VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore{ |
| 405 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES_KHR, | 405 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES, |
| 406 | .pNext = nullptr, | 406 | .pNext = nullptr, |
| 407 | .timelineSemaphore = true, | 407 | .timelineSemaphore = true, |
| 408 | }; | 408 | }; |
| 409 | SetNext(next, timeline_semaphore); | 409 | SetNext(next, timeline_semaphore); |
| 410 | 410 | ||
| 411 | VkPhysicalDevice16BitStorageFeaturesKHR bit16_storage{ | 411 | VkPhysicalDevice16BitStorageFeatures bit16_storage{ |
| 412 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR, | 412 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES, |
| 413 | .pNext = nullptr, | 413 | .pNext = nullptr, |
| 414 | .storageBuffer16BitAccess = true, | 414 | .storageBuffer16BitAccess = true, |
| 415 | .uniformAndStorageBuffer16BitAccess = true, | 415 | .uniformAndStorageBuffer16BitAccess = true, |
| @@ -418,8 +418,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 418 | }; | 418 | }; |
| 419 | SetNext(next, bit16_storage); | 419 | SetNext(next, bit16_storage); |
| 420 | 420 | ||
| 421 | VkPhysicalDevice8BitStorageFeaturesKHR bit8_storage{ | 421 | VkPhysicalDevice8BitStorageFeatures bit8_storage{ |
| 422 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR, | 422 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES, |
| 423 | .pNext = nullptr, | 423 | .pNext = nullptr, |
| 424 | .storageBuffer8BitAccess = false, | 424 | .storageBuffer8BitAccess = false, |
| 425 | .uniformAndStorageBuffer8BitAccess = true, | 425 | .uniformAndStorageBuffer8BitAccess = true, |
| @@ -436,32 +436,39 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 436 | }; | 436 | }; |
| 437 | SetNext(next, robustness2); | 437 | SetNext(next, robustness2); |
| 438 | 438 | ||
| 439 | VkPhysicalDeviceHostQueryResetFeaturesEXT host_query_reset{ | 439 | VkPhysicalDeviceHostQueryResetFeatures host_query_reset{ |
| 440 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT, | 440 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES, |
| 441 | .pNext = nullptr, | 441 | .pNext = nullptr, |
| 442 | .hostQueryReset = true, | 442 | .hostQueryReset = true, |
| 443 | }; | 443 | }; |
| 444 | SetNext(next, host_query_reset); | 444 | SetNext(next, host_query_reset); |
| 445 | 445 | ||
| 446 | VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointers{ | 446 | VkPhysicalDeviceVariablePointerFeatures variable_pointers{ |
| 447 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR, | 447 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES, |
| 448 | .pNext = nullptr, | 448 | .pNext = nullptr, |
| 449 | .variablePointersStorageBuffer = VK_TRUE, | 449 | .variablePointersStorageBuffer = VK_TRUE, |
| 450 | .variablePointers = VK_TRUE, | 450 | .variablePointers = VK_TRUE, |
| 451 | }; | 451 | }; |
| 452 | SetNext(next, variable_pointers); | 452 | SetNext(next, variable_pointers); |
| 453 | 453 | ||
| 454 | VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote{ | 454 | VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures demote{ |
| 455 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT, | 455 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES, |
| 456 | .pNext = nullptr, | 456 | .pNext = nullptr, |
| 457 | .shaderDemoteToHelperInvocation = true, | 457 | .shaderDemoteToHelperInvocation = true, |
| 458 | }; | 458 | }; |
| 459 | SetNext(next, demote); | 459 | SetNext(next, demote); |
| 460 | 460 | ||
| 461 | VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8; | 461 | VkPhysicalDeviceShaderDrawParametersFeatures draw_parameters{ |
| 462 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES, | ||
| 463 | .pNext = nullptr, | ||
| 464 | .shaderDrawParameters = true, | ||
| 465 | }; | ||
| 466 | SetNext(next, draw_parameters); | ||
| 467 | |||
| 468 | VkPhysicalDeviceShaderFloat16Int8Features float16_int8; | ||
| 462 | if (is_int8_supported || is_float16_supported) { | 469 | if (is_int8_supported || is_float16_supported) { |
| 463 | float16_int8 = { | 470 | float16_int8 = { |
| 464 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR, | 471 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES, |
| 465 | .pNext = nullptr, | 472 | .pNext = nullptr, |
| 466 | .shaderFloat16 = is_float16_supported, | 473 | .shaderFloat16 = is_float16_supported, |
| 467 | .shaderInt8 = is_int8_supported, | 474 | .shaderInt8 = is_int8_supported, |
| @@ -487,10 +494,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 487 | LOG_INFO(Render_Vulkan, "Device doesn't support passthrough geometry shaders"); | 494 | LOG_INFO(Render_Vulkan, "Device doesn't support passthrough geometry shaders"); |
| 488 | } | 495 | } |
| 489 | 496 | ||
| 490 | VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR std430_layout; | 497 | VkPhysicalDeviceUniformBufferStandardLayoutFeatures std430_layout; |
| 491 | if (khr_uniform_buffer_standard_layout) { | 498 | if (khr_uniform_buffer_standard_layout) { |
| 492 | std430_layout = { | 499 | std430_layout = { |
| 493 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR, | 500 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES, |
| 494 | .pNext = nullptr, | 501 | .pNext = nullptr, |
| 495 | .uniformBufferStandardLayout = true, | 502 | .uniformBufferStandardLayout = true, |
| 496 | }; | 503 | }; |
| @@ -608,10 +615,10 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR | |||
| 608 | LOG_INFO(Render_Vulkan, "Device doesn't support vertex input dynamic state"); | 615 | LOG_INFO(Render_Vulkan, "Device doesn't support vertex input dynamic state"); |
| 609 | } | 616 | } |
| 610 | 617 | ||
| 611 | VkPhysicalDeviceShaderAtomicInt64FeaturesKHR atomic_int64; | 618 | VkPhysicalDeviceShaderAtomicInt64Features atomic_int64; |
| 612 | if (ext_shader_atomic_int64) { | 619 | if (ext_shader_atomic_int64) { |
| 613 | atomic_int64 = { | 620 | atomic_int64 = { |
| 614 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES_KHR, | 621 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES, |
| 615 | .pNext = nullptr, | 622 | .pNext = nullptr, |
| 616 | .shaderBufferInt64Atomics = VK_TRUE, | 623 | .shaderBufferInt64Atomics = VK_TRUE, |
| 617 | .shaderSharedInt64Atomics = VK_TRUE, | 624 | .shaderSharedInt64Atomics = VK_TRUE, |
| @@ -896,28 +903,51 @@ std::string Device::GetDriverName() const { | |||
| 896 | } | 903 | } |
| 897 | } | 904 | } |
| 898 | 905 | ||
| 906 | static std::vector<const char*> ExtensionsRequiredForInstanceVersion(u32 available_version) { | ||
| 907 | std::vector<const char*> extensions{REQUIRED_EXTENSIONS.begin(), REQUIRED_EXTENSIONS.end()}; | ||
| 908 | |||
| 909 | if (available_version < VK_API_VERSION_1_2) { | ||
| 910 | extensions.insert(extensions.end(), REQUIRED_EXTENSIONS_BEFORE_1_2.begin(), | ||
| 911 | REQUIRED_EXTENSIONS_BEFORE_1_2.end()); | ||
| 912 | } | ||
| 913 | |||
| 914 | if (available_version < VK_API_VERSION_1_3) { | ||
| 915 | extensions.insert(extensions.end(), REQUIRED_EXTENSIONS_BEFORE_1_3.begin(), | ||
| 916 | REQUIRED_EXTENSIONS_BEFORE_1_3.end()); | ||
| 917 | } | ||
| 918 | |||
| 919 | return extensions; | ||
| 920 | } | ||
| 921 | |||
| 899 | void Device::CheckSuitability(bool requires_swapchain) const { | 922 | void Device::CheckSuitability(bool requires_swapchain) const { |
| 900 | std::bitset<REQUIRED_EXTENSIONS.size()> available_extensions; | 923 | std::vector<const char*> required_extensions = |
| 901 | bool has_swapchain = false; | 924 | ExtensionsRequiredForInstanceVersion(instance_version); |
| 902 | for (const VkExtensionProperties& property : physical.EnumerateDeviceExtensionProperties()) { | 925 | std::vector<const char*> available_extensions; |
| 903 | const std::string_view name{property.extensionName}; | 926 | |
| 904 | for (size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) { | 927 | if (requires_swapchain) { |
| 905 | if (available_extensions[i]) { | 928 | required_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); |
| 906 | continue; | ||
| 907 | } | ||
| 908 | available_extensions[i] = name == REQUIRED_EXTENSIONS[i]; | ||
| 909 | } | ||
| 910 | has_swapchain = has_swapchain || name == VK_KHR_SWAPCHAIN_EXTENSION_NAME; | ||
| 911 | } | 929 | } |
| 912 | for (size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) { | 930 | |
| 913 | if (available_extensions[i]) { | 931 | auto extension_properties = physical.EnumerateDeviceExtensionProperties(); |
| 914 | continue; | 932 | |
| 933 | for (const VkExtensionProperties& property : extension_properties) { | ||
| 934 | available_extensions.push_back(property.extensionName); | ||
| 935 | } | ||
| 936 | |||
| 937 | bool has_all_required_extensions = true; | ||
| 938 | for (const char* requirement_name : required_extensions) { | ||
| 939 | const bool found = | ||
| 940 | std::ranges::any_of(available_extensions, [&](const char* extension_name) { | ||
| 941 | return std::strcmp(requirement_name, extension_name) == 0; | ||
| 942 | }); | ||
| 943 | |||
| 944 | if (!found) { | ||
| 945 | LOG_ERROR(Render_Vulkan, "Missing required extension: {}", requirement_name); | ||
| 946 | has_all_required_extensions = false; | ||
| 915 | } | 947 | } |
| 916 | LOG_ERROR(Render_Vulkan, "Missing required extension: {}", REQUIRED_EXTENSIONS[i]); | ||
| 917 | throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); | ||
| 918 | } | 948 | } |
| 919 | if (requires_swapchain && !has_swapchain) { | 949 | |
| 920 | LOG_ERROR(Render_Vulkan, "Missing required extension: VK_KHR_swapchain"); | 950 | if (!has_all_required_extensions) { |
| 921 | throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); | 951 | throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); |
| 922 | } | 952 | } |
| 923 | 953 | ||
| @@ -940,27 +970,46 @@ void Device::CheckSuitability(bool requires_swapchain) const { | |||
| 940 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); | 970 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); |
| 941 | } | 971 | } |
| 942 | } | 972 | } |
| 943 | VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote{}; | 973 | VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures demote{}; |
| 944 | demote.sType = | 974 | demote.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES; |
| 945 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT; | ||
| 946 | demote.pNext = nullptr; | 975 | demote.pNext = nullptr; |
| 947 | 976 | ||
| 948 | VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointers{}; | 977 | VkPhysicalDeviceVariablePointerFeatures variable_pointers{}; |
| 949 | variable_pointers.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES_KHR; | 978 | variable_pointers.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES; |
| 950 | variable_pointers.pNext = &demote; | 979 | variable_pointers.pNext = &demote; |
| 951 | 980 | ||
| 952 | VkPhysicalDeviceRobustness2FeaturesEXT robustness2{}; | 981 | VkPhysicalDeviceRobustness2FeaturesEXT robustness2{}; |
| 953 | robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; | 982 | robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT; |
| 954 | robustness2.pNext = &variable_pointers; | 983 | robustness2.pNext = &variable_pointers; |
| 955 | 984 | ||
| 956 | VkPhysicalDeviceFeatures2KHR features2{}; | 985 | VkPhysicalDeviceTimelineSemaphoreFeatures timeline_semaphore{}; |
| 986 | timeline_semaphore.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES; | ||
| 987 | timeline_semaphore.pNext = &robustness2; | ||
| 988 | |||
| 989 | VkPhysicalDevice16BitStorageFeatures bit16_storage{}; | ||
| 990 | bit16_storage.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES; | ||
| 991 | bit16_storage.pNext = &timeline_semaphore; | ||
| 992 | |||
| 993 | VkPhysicalDevice8BitStorageFeatures bit8_storage{}; | ||
| 994 | bit8_storage.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES; | ||
| 995 | bit8_storage.pNext = &bit16_storage; | ||
| 996 | |||
| 997 | VkPhysicalDeviceHostQueryResetFeatures host_query_reset{}; | ||
| 998 | host_query_reset.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES; | ||
| 999 | host_query_reset.pNext = &bit8_storage; | ||
| 1000 | |||
| 1001 | VkPhysicalDeviceShaderDrawParametersFeatures draw_parameters{}; | ||
| 1002 | draw_parameters.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETER_FEATURES; | ||
| 1003 | draw_parameters.pNext = &host_query_reset; | ||
| 1004 | |||
| 1005 | VkPhysicalDeviceFeatures2 features2{}; | ||
| 957 | features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; | 1006 | features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| 958 | features2.pNext = &robustness2; | 1007 | features2.pNext = &draw_parameters; |
| 959 | 1008 | ||
| 960 | physical.GetFeatures2KHR(features2); | 1009 | physical.GetFeatures2(features2); |
| 961 | 1010 | ||
| 962 | const VkPhysicalDeviceFeatures& features{features2.features}; | 1011 | const VkPhysicalDeviceFeatures& features{features2.features}; |
| 963 | const std::array feature_report{ | 1012 | std::array feature_report{ |
| 964 | std::make_pair(features.robustBufferAccess, "robustBufferAccess"), | 1013 | std::make_pair(features.robustBufferAccess, "robustBufferAccess"), |
| 965 | std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"), | 1014 | std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"), |
| 966 | std::make_pair(features.imageCubeArray, "imageCubeArray"), | 1015 | std::make_pair(features.imageCubeArray, "imageCubeArray"), |
| @@ -976,6 +1025,7 @@ void Device::CheckSuitability(bool requires_swapchain) const { | |||
| 976 | std::make_pair(features.tessellationShader, "tessellationShader"), | 1025 | std::make_pair(features.tessellationShader, "tessellationShader"), |
| 977 | std::make_pair(features.sampleRateShading, "sampleRateShading"), | 1026 | std::make_pair(features.sampleRateShading, "sampleRateShading"), |
| 978 | std::make_pair(features.dualSrcBlend, "dualSrcBlend"), | 1027 | std::make_pair(features.dualSrcBlend, "dualSrcBlend"), |
| 1028 | std::make_pair(features.logicOp, "logicOp"), | ||
| 979 | std::make_pair(features.occlusionQueryPrecise, "occlusionQueryPrecise"), | 1029 | std::make_pair(features.occlusionQueryPrecise, "occlusionQueryPrecise"), |
| 980 | std::make_pair(features.fragmentStoresAndAtomics, "fragmentStoresAndAtomics"), | 1030 | std::make_pair(features.fragmentStoresAndAtomics, "fragmentStoresAndAtomics"), |
| 981 | std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"), | 1031 | std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"), |
| @@ -983,27 +1033,38 @@ void Device::CheckSuitability(bool requires_swapchain) const { | |||
| 983 | "shaderStorageImageWriteWithoutFormat"), | 1033 | "shaderStorageImageWriteWithoutFormat"), |
| 984 | std::make_pair(features.shaderClipDistance, "shaderClipDistance"), | 1034 | std::make_pair(features.shaderClipDistance, "shaderClipDistance"), |
| 985 | std::make_pair(features.shaderCullDistance, "shaderCullDistance"), | 1035 | std::make_pair(features.shaderCullDistance, "shaderCullDistance"), |
| 986 | std::make_pair(demote.shaderDemoteToHelperInvocation, "shaderDemoteToHelperInvocation"), | ||
| 987 | std::make_pair(variable_pointers.variablePointers, "variablePointers"), | 1036 | std::make_pair(variable_pointers.variablePointers, "variablePointers"), |
| 988 | std::make_pair(variable_pointers.variablePointersStorageBuffer, | 1037 | std::make_pair(variable_pointers.variablePointersStorageBuffer, |
| 989 | "variablePointersStorageBuffer"), | 1038 | "variablePointersStorageBuffer"), |
| 990 | std::make_pair(robustness2.robustBufferAccess2, "robustBufferAccess2"), | 1039 | std::make_pair(robustness2.robustBufferAccess2, "robustBufferAccess2"), |
| 991 | std::make_pair(robustness2.robustImageAccess2, "robustImageAccess2"), | 1040 | std::make_pair(robustness2.robustImageAccess2, "robustImageAccess2"), |
| 992 | std::make_pair(robustness2.nullDescriptor, "nullDescriptor"), | 1041 | std::make_pair(robustness2.nullDescriptor, "nullDescriptor"), |
| 1042 | std::make_pair(demote.shaderDemoteToHelperInvocation, "shaderDemoteToHelperInvocation"), | ||
| 1043 | std::make_pair(timeline_semaphore.timelineSemaphore, "timelineSemaphore"), | ||
| 1044 | std::make_pair(bit16_storage.storageBuffer16BitAccess, "storageBuffer16BitAccess"), | ||
| 1045 | std::make_pair(bit16_storage.uniformAndStorageBuffer16BitAccess, | ||
| 1046 | "uniformAndStorageBuffer16BitAccess"), | ||
| 1047 | std::make_pair(bit8_storage.uniformAndStorageBuffer8BitAccess, | ||
| 1048 | "uniformAndStorageBuffer8BitAccess"), | ||
| 1049 | std::make_pair(host_query_reset.hostQueryReset, "hostQueryReset"), | ||
| 1050 | std::make_pair(draw_parameters.shaderDrawParameters, "shaderDrawParameters"), | ||
| 993 | }; | 1051 | }; |
| 1052 | |||
| 1053 | bool has_all_required_features = true; | ||
| 994 | for (const auto& [is_supported, name] : feature_report) { | 1054 | for (const auto& [is_supported, name] : feature_report) { |
| 995 | if (is_supported) { | 1055 | if (!is_supported) { |
| 996 | continue; | 1056 | LOG_ERROR(Render_Vulkan, "Missing required feature: {}", name); |
| 1057 | has_all_required_features = false; | ||
| 997 | } | 1058 | } |
| 998 | LOG_ERROR(Render_Vulkan, "Missing required feature: {}", name); | 1059 | } |
| 1060 | |||
| 1061 | if (!has_all_required_features) { | ||
| 999 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); | 1062 | throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT); |
| 1000 | } | 1063 | } |
| 1001 | } | 1064 | } |
| 1002 | 1065 | ||
| 1003 | std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | 1066 | std::vector<const char*> Device::LoadExtensions(bool requires_surface) { |
| 1004 | std::vector<const char*> extensions; | 1067 | std::vector<const char*> extensions = ExtensionsRequiredForInstanceVersion(instance_version); |
| 1005 | extensions.reserve(8 + REQUIRED_EXTENSIONS.size()); | ||
| 1006 | extensions.insert(extensions.begin(), REQUIRED_EXTENSIONS.begin(), REQUIRED_EXTENSIONS.end()); | ||
| 1007 | if (requires_surface) { | 1068 | if (requires_surface) { |
| 1008 | extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); | 1069 | extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); |
| 1009 | } | 1070 | } |
| @@ -1079,37 +1140,37 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1079 | VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME, false); | 1140 | VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME, false); |
| 1080 | } | 1141 | } |
| 1081 | } | 1142 | } |
| 1082 | VkPhysicalDeviceFeatures2KHR features{}; | 1143 | VkPhysicalDeviceFeatures2 features{}; |
| 1083 | features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; | 1144 | features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| 1084 | 1145 | ||
| 1085 | VkPhysicalDeviceProperties2KHR physical_properties{}; | 1146 | VkPhysicalDeviceProperties2 physical_properties{}; |
| 1086 | physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; | 1147 | physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; |
| 1087 | 1148 | ||
| 1088 | if (has_khr_shader_float16_int8) { | 1149 | if (has_khr_shader_float16_int8) { |
| 1089 | VkPhysicalDeviceFloat16Int8FeaturesKHR float16_int8_features; | 1150 | VkPhysicalDeviceShaderFloat16Int8Features float16_int8_features; |
| 1090 | float16_int8_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR; | 1151 | float16_int8_features.sType = |
| 1152 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES; | ||
| 1091 | float16_int8_features.pNext = nullptr; | 1153 | float16_int8_features.pNext = nullptr; |
| 1092 | features.pNext = &float16_int8_features; | 1154 | features.pNext = &float16_int8_features; |
| 1093 | 1155 | ||
| 1094 | physical.GetFeatures2KHR(features); | 1156 | physical.GetFeatures2(features); |
| 1095 | is_float16_supported = float16_int8_features.shaderFloat16; | 1157 | is_float16_supported = float16_int8_features.shaderFloat16; |
| 1096 | is_int8_supported = float16_int8_features.shaderInt8; | 1158 | is_int8_supported = float16_int8_features.shaderInt8; |
| 1097 | extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); | 1159 | extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME); |
| 1098 | } | 1160 | } |
| 1099 | if (has_ext_subgroup_size_control) { | 1161 | if (has_ext_subgroup_size_control) { |
| 1100 | VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroup_features; | 1162 | VkPhysicalDeviceSubgroupSizeControlFeatures subgroup_features; |
| 1101 | subgroup_features.sType = | 1163 | subgroup_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES; |
| 1102 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_FEATURES_EXT; | ||
| 1103 | subgroup_features.pNext = nullptr; | 1164 | subgroup_features.pNext = nullptr; |
| 1104 | features.pNext = &subgroup_features; | 1165 | features.pNext = &subgroup_features; |
| 1105 | physical.GetFeatures2KHR(features); | 1166 | physical.GetFeatures2(features); |
| 1106 | 1167 | ||
| 1107 | VkPhysicalDeviceSubgroupSizeControlPropertiesEXT subgroup_properties; | 1168 | VkPhysicalDeviceSubgroupSizeControlProperties subgroup_properties; |
| 1108 | subgroup_properties.sType = | 1169 | subgroup_properties.sType = |
| 1109 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES_EXT; | 1170 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES; |
| 1110 | subgroup_properties.pNext = nullptr; | 1171 | subgroup_properties.pNext = nullptr; |
| 1111 | physical_properties.pNext = &subgroup_properties; | 1172 | physical_properties.pNext = &subgroup_properties; |
| 1112 | physical.GetProperties2KHR(physical_properties); | 1173 | physical.GetProperties2(physical_properties); |
| 1113 | 1174 | ||
| 1114 | is_warp_potentially_bigger = subgroup_properties.maxSubgroupSize > GuestWarpSize; | 1175 | is_warp_potentially_bigger = subgroup_properties.maxSubgroupSize > GuestWarpSize; |
| 1115 | 1176 | ||
| @@ -1128,7 +1189,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1128 | provoking_vertex.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT; | 1189 | provoking_vertex.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT; |
| 1129 | provoking_vertex.pNext = nullptr; | 1190 | provoking_vertex.pNext = nullptr; |
| 1130 | features.pNext = &provoking_vertex; | 1191 | features.pNext = &provoking_vertex; |
| 1131 | physical.GetFeatures2KHR(features); | 1192 | physical.GetFeatures2(features); |
| 1132 | 1193 | ||
| 1133 | if (provoking_vertex.provokingVertexLast && | 1194 | if (provoking_vertex.provokingVertexLast && |
| 1134 | provoking_vertex.transformFeedbackPreservesProvokingVertex) { | 1195 | provoking_vertex.transformFeedbackPreservesProvokingVertex) { |
| @@ -1142,7 +1203,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1142 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT; | 1203 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT; |
| 1143 | vertex_input.pNext = nullptr; | 1204 | vertex_input.pNext = nullptr; |
| 1144 | features.pNext = &vertex_input; | 1205 | features.pNext = &vertex_input; |
| 1145 | physical.GetFeatures2KHR(features); | 1206 | physical.GetFeatures2(features); |
| 1146 | 1207 | ||
| 1147 | if (vertex_input.vertexInputDynamicState) { | 1208 | if (vertex_input.vertexInputDynamicState) { |
| 1148 | extensions.push_back(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); | 1209 | extensions.push_back(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); |
| @@ -1154,7 +1215,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1154 | atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES; | 1215 | atomic_int64.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_INT64_FEATURES; |
| 1155 | atomic_int64.pNext = nullptr; | 1216 | atomic_int64.pNext = nullptr; |
| 1156 | features.pNext = &atomic_int64; | 1217 | features.pNext = &atomic_int64; |
| 1157 | physical.GetFeatures2KHR(features); | 1218 | physical.GetFeatures2(features); |
| 1158 | 1219 | ||
| 1159 | if (atomic_int64.shaderBufferInt64Atomics && atomic_int64.shaderSharedInt64Atomics) { | 1220 | if (atomic_int64.shaderBufferInt64Atomics && atomic_int64.shaderSharedInt64Atomics) { |
| 1160 | extensions.push_back(VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); | 1221 | extensions.push_back(VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); |
| @@ -1166,13 +1227,13 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1166 | tfb_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; | 1227 | tfb_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT; |
| 1167 | tfb_features.pNext = nullptr; | 1228 | tfb_features.pNext = nullptr; |
| 1168 | features.pNext = &tfb_features; | 1229 | features.pNext = &tfb_features; |
| 1169 | physical.GetFeatures2KHR(features); | 1230 | physical.GetFeatures2(features); |
| 1170 | 1231 | ||
| 1171 | VkPhysicalDeviceTransformFeedbackPropertiesEXT tfb_properties; | 1232 | VkPhysicalDeviceTransformFeedbackPropertiesEXT tfb_properties; |
| 1172 | tfb_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; | 1233 | tfb_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT; |
| 1173 | tfb_properties.pNext = nullptr; | 1234 | tfb_properties.pNext = nullptr; |
| 1174 | physical_properties.pNext = &tfb_properties; | 1235 | physical_properties.pNext = &tfb_properties; |
| 1175 | physical.GetProperties2KHR(physical_properties); | 1236 | physical.GetProperties2(physical_properties); |
| 1176 | 1237 | ||
| 1177 | if (tfb_features.transformFeedback && tfb_features.geometryStreams && | 1238 | if (tfb_features.transformFeedback && tfb_features.geometryStreams && |
| 1178 | tfb_properties.maxTransformFeedbackStreams >= 4 && | 1239 | tfb_properties.maxTransformFeedbackStreams >= 4 && |
| @@ -1187,7 +1248,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1187 | border_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; | 1248 | border_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT; |
| 1188 | border_features.pNext = nullptr; | 1249 | border_features.pNext = nullptr; |
| 1189 | features.pNext = &border_features; | 1250 | features.pNext = &border_features; |
| 1190 | physical.GetFeatures2KHR(features); | 1251 | physical.GetFeatures2(features); |
| 1191 | 1252 | ||
| 1192 | if (border_features.customBorderColors && border_features.customBorderColorWithoutFormat) { | 1253 | if (border_features.customBorderColors && border_features.customBorderColorWithoutFormat) { |
| 1193 | extensions.push_back(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); | 1254 | extensions.push_back(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); |
| @@ -1200,7 +1261,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1200 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; | 1261 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT; |
| 1201 | extended_dynamic_state.pNext = nullptr; | 1262 | extended_dynamic_state.pNext = nullptr; |
| 1202 | features.pNext = &extended_dynamic_state; | 1263 | features.pNext = &extended_dynamic_state; |
| 1203 | physical.GetFeatures2KHR(features); | 1264 | physical.GetFeatures2(features); |
| 1204 | 1265 | ||
| 1205 | if (extended_dynamic_state.extendedDynamicState) { | 1266 | if (extended_dynamic_state.extendedDynamicState) { |
| 1206 | extensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); | 1267 | extensions.push_back(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); |
| @@ -1212,7 +1273,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1212 | line_raster.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT; | 1273 | line_raster.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT; |
| 1213 | line_raster.pNext = nullptr; | 1274 | line_raster.pNext = nullptr; |
| 1214 | features.pNext = &line_raster; | 1275 | features.pNext = &line_raster; |
| 1215 | physical.GetFeatures2KHR(features); | 1276 | physical.GetFeatures2(features); |
| 1216 | if (line_raster.rectangularLines && line_raster.smoothLines) { | 1277 | if (line_raster.rectangularLines && line_raster.smoothLines) { |
| 1217 | extensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME); | 1278 | extensions.push_back(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME); |
| 1218 | ext_line_rasterization = true; | 1279 | ext_line_rasterization = true; |
| @@ -1224,7 +1285,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1224 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR; | 1285 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_FEATURES_KHR; |
| 1225 | layout.pNext = nullptr; | 1286 | layout.pNext = nullptr; |
| 1226 | features.pNext = &layout; | 1287 | features.pNext = &layout; |
| 1227 | physical.GetFeatures2KHR(features); | 1288 | physical.GetFeatures2(features); |
| 1228 | 1289 | ||
| 1229 | if (layout.workgroupMemoryExplicitLayout && | 1290 | if (layout.workgroupMemoryExplicitLayout && |
| 1230 | layout.workgroupMemoryExplicitLayout8BitAccess && | 1291 | layout.workgroupMemoryExplicitLayout8BitAccess && |
| @@ -1240,7 +1301,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1240 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR; | 1301 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR; |
| 1241 | executable_properties.pNext = nullptr; | 1302 | executable_properties.pNext = nullptr; |
| 1242 | features.pNext = &executable_properties; | 1303 | features.pNext = &executable_properties; |
| 1243 | physical.GetFeatures2KHR(features); | 1304 | physical.GetFeatures2(features); |
| 1244 | 1305 | ||
| 1245 | if (executable_properties.pipelineExecutableInfo) { | 1306 | if (executable_properties.pipelineExecutableInfo) { |
| 1246 | extensions.push_back(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); | 1307 | extensions.push_back(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); |
| @@ -1253,7 +1314,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1253 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT; | 1314 | VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT; |
| 1254 | primitive_topology_list_restart.pNext = nullptr; | 1315 | primitive_topology_list_restart.pNext = nullptr; |
| 1255 | features.pNext = &primitive_topology_list_restart; | 1316 | features.pNext = &primitive_topology_list_restart; |
| 1256 | physical.GetFeatures2KHR(features); | 1317 | physical.GetFeatures2(features); |
| 1257 | 1318 | ||
| 1258 | is_topology_list_restart_supported = | 1319 | is_topology_list_restart_supported = |
| 1259 | primitive_topology_list_restart.primitiveTopologyListRestart; | 1320 | primitive_topology_list_restart.primitiveTopologyListRestart; |
| @@ -1271,7 +1332,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 1271 | push_descriptor.pNext = nullptr; | 1332 | push_descriptor.pNext = nullptr; |
| 1272 | 1333 | ||
| 1273 | physical_properties.pNext = &push_descriptor; | 1334 | physical_properties.pNext = &push_descriptor; |
| 1274 | physical.GetProperties2KHR(physical_properties); | 1335 | physical.GetProperties2(physical_properties); |
| 1275 | 1336 | ||
| 1276 | max_push_descriptors = push_descriptor.maxPushDescriptors; | 1337 | max_push_descriptors = push_descriptor.maxPushDescriptors; |
| 1277 | } | 1338 | } |
| @@ -1322,18 +1383,18 @@ void Device::SetupFeatures() { | |||
| 1322 | } | 1383 | } |
| 1323 | 1384 | ||
| 1324 | void Device::SetupProperties() { | 1385 | void Device::SetupProperties() { |
| 1325 | float_controls.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES_KHR; | 1386 | float_controls.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES; |
| 1326 | 1387 | ||
| 1327 | VkPhysicalDeviceProperties2KHR properties2{}; | 1388 | VkPhysicalDeviceProperties2KHR properties2{}; |
| 1328 | properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR; | 1389 | properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; |
| 1329 | properties2.pNext = &float_controls; | 1390 | properties2.pNext = &float_controls; |
| 1330 | 1391 | ||
| 1331 | physical.GetProperties2KHR(properties2); | 1392 | physical.GetProperties2(properties2); |
| 1332 | } | 1393 | } |
| 1333 | 1394 | ||
| 1334 | void Device::CollectTelemetryParameters() { | 1395 | void Device::CollectTelemetryParameters() { |
| 1335 | VkPhysicalDeviceDriverPropertiesKHR driver{ | 1396 | VkPhysicalDeviceDriverProperties driver{ |
| 1336 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR, | 1397 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES, |
| 1337 | .pNext = nullptr, | 1398 | .pNext = nullptr, |
| 1338 | .driverID = {}, | 1399 | .driverID = {}, |
| 1339 | .driverName = {}, | 1400 | .driverName = {}, |
| @@ -1341,12 +1402,12 @@ void Device::CollectTelemetryParameters() { | |||
| 1341 | .conformanceVersion = {}, | 1402 | .conformanceVersion = {}, |
| 1342 | }; | 1403 | }; |
| 1343 | 1404 | ||
| 1344 | VkPhysicalDeviceProperties2KHR device_properties{ | 1405 | VkPhysicalDeviceProperties2 device_properties{ |
| 1345 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR, | 1406 | .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, |
| 1346 | .pNext = &driver, | 1407 | .pNext = &driver, |
| 1347 | .properties = {}, | 1408 | .properties = {}, |
| 1348 | }; | 1409 | }; |
| 1349 | physical.GetProperties2KHR(device_properties); | 1410 | physical.GetProperties2(device_properties); |
| 1350 | 1411 | ||
| 1351 | driver_id = driver.driverID; | 1412 | driver_id = driver.driverID; |
| 1352 | vendor_name = driver.driverName; | 1413 | vendor_name = driver.driverName; |
| @@ -1402,23 +1463,10 @@ void Device::CollectToolingInfo() { | |||
| 1402 | if (!ext_tooling_info) { | 1463 | if (!ext_tooling_info) { |
| 1403 | return; | 1464 | return; |
| 1404 | } | 1465 | } |
| 1405 | const auto vkGetPhysicalDeviceToolPropertiesEXT = | 1466 | auto tools{physical.GetPhysicalDeviceToolProperties()}; |
| 1406 | reinterpret_cast<PFN_vkGetPhysicalDeviceToolPropertiesEXT>( | 1467 | for (const VkPhysicalDeviceToolProperties& tool : tools) { |
| 1407 | dld.vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceToolPropertiesEXT")); | ||
| 1408 | if (!vkGetPhysicalDeviceToolPropertiesEXT) { | ||
| 1409 | return; | ||
| 1410 | } | ||
| 1411 | u32 tool_count = 0; | ||
| 1412 | if (vkGetPhysicalDeviceToolPropertiesEXT(physical, &tool_count, nullptr) != VK_SUCCESS) { | ||
| 1413 | return; | ||
| 1414 | } | ||
| 1415 | std::vector<VkPhysicalDeviceToolPropertiesEXT> tools(tool_count); | ||
| 1416 | if (vkGetPhysicalDeviceToolPropertiesEXT(physical, &tool_count, tools.data()) != VK_SUCCESS) { | ||
| 1417 | return; | ||
| 1418 | } | ||
| 1419 | for (const VkPhysicalDeviceToolPropertiesEXT& tool : tools) { | ||
| 1420 | const std::string_view name = tool.name; | 1468 | const std::string_view name = tool.name; |
| 1421 | LOG_INFO(Render_Vulkan, "{}", name); | 1469 | LOG_INFO(Render_Vulkan, "Attached debugging tool: {}", name); |
| 1422 | has_renderdoc = has_renderdoc || name == "RenderDoc"; | 1470 | has_renderdoc = has_renderdoc || name == "RenderDoc"; |
| 1423 | has_nsight_graphics = has_nsight_graphics || name == "NVIDIA Nsight Graphics"; | 1471 | has_nsight_graphics = has_nsight_graphics || name == "NVIDIA Nsight Graphics"; |
| 1424 | } | 1472 | } |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index d7cc6c593..db802437c 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -211,18 +211,13 @@ public: | |||
| 211 | return khr_uniform_buffer_standard_layout; | 211 | return khr_uniform_buffer_standard_layout; |
| 212 | } | 212 | } |
| 213 | 213 | ||
| 214 | /// Returns true if the device supports VK_KHR_spirv_1_4. | ||
| 215 | bool IsKhrSpirv1_4Supported() const { | ||
| 216 | return khr_spirv_1_4; | ||
| 217 | } | ||
| 218 | |||
| 219 | /// Returns true if the device supports VK_KHR_push_descriptor. | 214 | /// Returns true if the device supports VK_KHR_push_descriptor. |
| 220 | bool IsKhrPushDescriptorSupported() const { | 215 | bool IsKhrPushDescriptorSupported() const { |
| 221 | return khr_push_descriptor; | 216 | return khr_push_descriptor; |
| 222 | } | 217 | } |
| 223 | 218 | ||
| 224 | /// Returns true if VK_KHR_pipeline_executable_properties is enabled. | 219 | /// Returns true if VK_KHR_pipeline_executable_properties is enabled. |
| 225 | bool IsKhrPipelineEexecutablePropertiesEnabled() const { | 220 | bool IsKhrPipelineExecutablePropertiesEnabled() const { |
| 226 | return khr_pipeline_executable_properties; | 221 | return khr_pipeline_executable_properties; |
| 227 | } | 222 | } |
| 228 | 223 | ||
| @@ -316,6 +311,17 @@ public: | |||
| 316 | return ext_shader_atomic_int64; | 311 | return ext_shader_atomic_int64; |
| 317 | } | 312 | } |
| 318 | 313 | ||
| 314 | /// Returns the minimum supported version of SPIR-V. | ||
| 315 | u32 SupportedSpirvVersion() const { | ||
| 316 | if (instance_version >= VK_API_VERSION_1_3) { | ||
| 317 | return 0x00010600U; | ||
| 318 | } | ||
| 319 | if (khr_spirv_1_4) { | ||
| 320 | return 0x00010400U; | ||
| 321 | } | ||
| 322 | return 0x00010000U; | ||
| 323 | } | ||
| 324 | |||
| 319 | /// Returns true when a known debugging tool is attached. | 325 | /// Returns true when a known debugging tool is attached. |
| 320 | bool HasDebuggingToolAttached() const { | 326 | bool HasDebuggingToolAttached() const { |
| 321 | return has_renderdoc || has_nsight_graphics; | 327 | return has_renderdoc || has_nsight_graphics; |
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp index a082e3059..562039b56 100644 --- a/src/video_core/vulkan_common/vulkan_instance.cpp +++ b/src/video_core/vulkan_common/vulkan_instance.cpp | |||
| @@ -9,18 +9,21 @@ | |||
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "common/dynamic_library.h" | 10 | #include "common/dynamic_library.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/polyfill_ranges.h" | ||
| 12 | #include "core/frontend/emu_window.h" | 13 | #include "core/frontend/emu_window.h" |
| 13 | #include "video_core/vulkan_common/vulkan_instance.h" | 14 | #include "video_core/vulkan_common/vulkan_instance.h" |
| 14 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 15 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
| 15 | 16 | ||
| 16 | // Include these late to avoid polluting previous headers | 17 | // Include these late to avoid polluting previous headers |
| 17 | #ifdef _WIN32 | 18 | #if defined(_WIN32) |
| 18 | #include <windows.h> | 19 | #include <windows.h> |
| 19 | // ensure include order | 20 | // ensure include order |
| 20 | #include <vulkan/vulkan_win32.h> | 21 | #include <vulkan/vulkan_win32.h> |
| 21 | #endif | 22 | #elif defined(__APPLE__) |
| 22 | 23 | #include <vulkan/vulkan_macos.h> | |
| 23 | #if !defined(_WIN32) && !defined(__APPLE__) | 24 | #elif defined(__ANDROID__) |
| 25 | #include <vulkan/vulkan_android.h> | ||
| 26 | #else | ||
| 24 | #include <X11/Xlib.h> | 27 | #include <X11/Xlib.h> |
| 25 | #include <vulkan/vulkan_wayland.h> | 28 | #include <vulkan/vulkan_wayland.h> |
| 26 | #include <vulkan/vulkan_xlib.h> | 29 | #include <vulkan/vulkan_xlib.h> |
| @@ -39,8 +42,15 @@ namespace { | |||
| 39 | case Core::Frontend::WindowSystemType::Windows: | 42 | case Core::Frontend::WindowSystemType::Windows: |
| 40 | extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); | 43 | extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME); |
| 41 | break; | 44 | break; |
| 42 | #endif | 45 | #elif defined(__APPLE__) |
| 43 | #if !defined(_WIN32) && !defined(__APPLE__) | 46 | case Core::Frontend::WindowSystemType::Cocoa: |
| 47 | extensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME); | ||
| 48 | break; | ||
| 49 | #elif defined(__ANDROID__) | ||
| 50 | case Core::Frontend::WindowSystemType::Android: | ||
| 51 | extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME); | ||
| 52 | break; | ||
| 53 | #else | ||
| 44 | case Core::Frontend::WindowSystemType::X11: | 54 | case Core::Frontend::WindowSystemType::X11: |
| 45 | extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); | 55 | extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); |
| 46 | break; | 56 | break; |
| @@ -59,6 +69,10 @@ namespace { | |||
| 59 | extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); | 69 | extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); |
| 60 | } | 70 | } |
| 61 | extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); | 71 | extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME); |
| 72 | |||
| 73 | #ifdef __APPLE__ | ||
| 74 | extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME); | ||
| 75 | #endif | ||
| 62 | return extensions; | 76 | return extensions; |
| 63 | } | 77 | } |
| 64 | 78 | ||
| @@ -140,7 +154,7 @@ vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceD | |||
| 140 | } | 154 | } |
| 141 | vk::Instance instance = | 155 | vk::Instance instance = |
| 142 | std::async([&] { | 156 | std::async([&] { |
| 143 | return vk::Instance::Create(required_version, layers, extensions, dld); | 157 | return vk::Instance::Create(available_version, layers, extensions, dld); |
| 144 | }).get(); | 158 | }).get(); |
| 145 | if (!vk::Load(*instance, dld)) { | 159 | if (!vk::Load(*instance, dld)) { |
| 146 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers"); | 160 | LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers"); |
diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index 6442898bd..1732866e0 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include "common/assert.h" | 12 | #include "common/assert.h" |
| 13 | #include "common/common_types.h" | 13 | #include "common/common_types.h" |
| 14 | #include "common/logging/log.h" | 14 | #include "common/logging/log.h" |
| 15 | #include "common/polyfill_ranges.h" | ||
| 15 | #include "video_core/vulkan_common/vulkan_device.h" | 16 | #include "video_core/vulkan_common/vulkan_device.h" |
| 16 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" | 17 | #include "video_core/vulkan_common/vulkan_memory_allocator.h" |
| 17 | #include "video_core/vulkan_common/vulkan_wrapper.h" | 18 | #include "video_core/vulkan_common/vulkan_wrapper.h" |
diff --git a/src/video_core/vulkan_common/vulkan_surface.cpp b/src/video_core/vulkan_common/vulkan_surface.cpp index 69f9c494b..fa9bafa20 100644 --- a/src/video_core/vulkan_common/vulkan_surface.cpp +++ b/src/video_core/vulkan_common/vulkan_surface.cpp | |||
| @@ -11,9 +11,11 @@ | |||
| 11 | #include <windows.h> | 11 | #include <windows.h> |
| 12 | // ensure include order | 12 | // ensure include order |
| 13 | #include <vulkan/vulkan_win32.h> | 13 | #include <vulkan/vulkan_win32.h> |
| 14 | #endif | 14 | #elif defined(__APPLE__) |
| 15 | 15 | #include <vulkan/vulkan_macos.h> | |
| 16 | #if !defined(_WIN32) && !defined(__APPLE__) | 16 | #elif defined(__ANDROID__) |
| 17 | #include <vulkan/vulkan_android.h> | ||
| 18 | #else | ||
| 17 | #include <X11/Xlib.h> | 19 | #include <X11/Xlib.h> |
| 18 | #include <vulkan/vulkan_wayland.h> | 20 | #include <vulkan/vulkan_wayland.h> |
| 19 | #include <vulkan/vulkan_xlib.h> | 21 | #include <vulkan/vulkan_xlib.h> |
| @@ -40,8 +42,33 @@ vk::SurfaceKHR CreateSurface(const vk::Instance& instance, | |||
| 40 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | 42 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
| 41 | } | 43 | } |
| 42 | } | 44 | } |
| 43 | #endif | 45 | #elif defined(__APPLE__) |
| 44 | #if !defined(_WIN32) && !defined(__APPLE__) | 46 | if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) { |
| 47 | const VkMacOSSurfaceCreateInfoMVK mvk_ci{VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK, | ||
| 48 | nullptr, 0, window_info.render_surface}; | ||
| 49 | const auto vkCreateMacOSSurfaceMVK = reinterpret_cast<PFN_vkCreateMacOSSurfaceMVK>( | ||
| 50 | dld.vkGetInstanceProcAddr(*instance, "vkCreateMacOSSurfaceMVK")); | ||
| 51 | if (!vkCreateMacOSSurfaceMVK || | ||
| 52 | vkCreateMacOSSurfaceMVK(*instance, &mvk_ci, nullptr, &unsafe_surface) != VK_SUCCESS) { | ||
| 53 | LOG_ERROR(Render_Vulkan, "Failed to initialize Metal surface"); | ||
| 54 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | #elif defined(__ANDROID__) | ||
| 58 | if (window_info.type == Core::Frontend::WindowSystemType::Android) { | ||
| 59 | const VkAndroidSurfaceCreateInfoKHR android_ci{ | ||
| 60 | VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, nullptr, 0, | ||
| 61 | reinterpret_cast<ANativeWindow*>(window_info.render_surface)}; | ||
| 62 | const auto vkCreateAndroidSurfaceKHR = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>( | ||
| 63 | dld.vkGetInstanceProcAddr(*instance, "vkCreateAndroidSurfaceKHR")); | ||
| 64 | if (!vkCreateAndroidSurfaceKHR || | ||
| 65 | vkCreateAndroidSurfaceKHR(*instance, &android_ci, nullptr, &unsafe_surface) != | ||
| 66 | VK_SUCCESS) { | ||
| 67 | LOG_ERROR(Render_Vulkan, "Failed to initialize Android surface"); | ||
| 68 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | ||
| 69 | } | ||
| 70 | } | ||
| 71 | #else | ||
| 45 | if (window_info.type == Core::Frontend::WindowSystemType::X11) { | 72 | if (window_info.type == Core::Frontend::WindowSystemType::X11) { |
| 46 | const VkXlibSurfaceCreateInfoKHR xlib_ci{ | 73 | const VkXlibSurfaceCreateInfoKHR xlib_ci{ |
| 47 | VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0, | 74 | VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0, |
| @@ -70,6 +97,7 @@ vk::SurfaceKHR CreateSurface(const vk::Instance& instance, | |||
| 70 | } | 97 | } |
| 71 | } | 98 | } |
| 72 | #endif | 99 | #endif |
| 100 | |||
| 73 | if (!unsafe_surface) { | 101 | if (!unsafe_surface) { |
| 74 | LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform"); | 102 | LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform"); |
| 75 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); | 103 | throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED); |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 2ad98dcfe..bda10ee2f 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -130,7 +130,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 130 | X(vkCreateComputePipelines); | 130 | X(vkCreateComputePipelines); |
| 131 | X(vkCreateDescriptorPool); | 131 | X(vkCreateDescriptorPool); |
| 132 | X(vkCreateDescriptorSetLayout); | 132 | X(vkCreateDescriptorSetLayout); |
| 133 | X(vkCreateDescriptorUpdateTemplateKHR); | 133 | X(vkCreateDescriptorUpdateTemplate); |
| 134 | X(vkCreateEvent); | 134 | X(vkCreateEvent); |
| 135 | X(vkCreateFence); | 135 | X(vkCreateFence); |
| 136 | X(vkCreateFramebuffer); | 136 | X(vkCreateFramebuffer); |
| @@ -149,7 +149,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 149 | X(vkDestroyCommandPool); | 149 | X(vkDestroyCommandPool); |
| 150 | X(vkDestroyDescriptorPool); | 150 | X(vkDestroyDescriptorPool); |
| 151 | X(vkDestroyDescriptorSetLayout); | 151 | X(vkDestroyDescriptorSetLayout); |
| 152 | X(vkDestroyDescriptorUpdateTemplateKHR); | 152 | X(vkDestroyDescriptorUpdateTemplate); |
| 153 | X(vkDestroyEvent); | 153 | X(vkDestroyEvent); |
| 154 | X(vkDestroyFence); | 154 | X(vkDestroyFence); |
| 155 | X(vkDestroyFramebuffer); | 155 | X(vkDestroyFramebuffer); |
| @@ -180,18 +180,29 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept { | |||
| 180 | X(vkGetQueryPoolResults); | 180 | X(vkGetQueryPoolResults); |
| 181 | X(vkGetPipelineExecutablePropertiesKHR); | 181 | X(vkGetPipelineExecutablePropertiesKHR); |
| 182 | X(vkGetPipelineExecutableStatisticsKHR); | 182 | X(vkGetPipelineExecutableStatisticsKHR); |
| 183 | X(vkGetSemaphoreCounterValueKHR); | 183 | X(vkGetSemaphoreCounterValue); |
| 184 | X(vkMapMemory); | 184 | X(vkMapMemory); |
| 185 | X(vkQueueSubmit); | 185 | X(vkQueueSubmit); |
| 186 | X(vkResetFences); | 186 | X(vkResetFences); |
| 187 | X(vkResetQueryPoolEXT); | 187 | X(vkResetQueryPool); |
| 188 | X(vkSetDebugUtilsObjectNameEXT); | 188 | X(vkSetDebugUtilsObjectNameEXT); |
| 189 | X(vkSetDebugUtilsObjectTagEXT); | 189 | X(vkSetDebugUtilsObjectTagEXT); |
| 190 | X(vkUnmapMemory); | 190 | X(vkUnmapMemory); |
| 191 | X(vkUpdateDescriptorSetWithTemplateKHR); | 191 | X(vkUpdateDescriptorSetWithTemplate); |
| 192 | X(vkUpdateDescriptorSets); | 192 | X(vkUpdateDescriptorSets); |
| 193 | X(vkWaitForFences); | 193 | X(vkWaitForFences); |
| 194 | X(vkWaitSemaphoresKHR); | 194 | X(vkWaitSemaphores); |
| 195 | |||
| 196 | // Support for timeline semaphores is mandatory in Vulkan 1.2 | ||
| 197 | if (!dld.vkGetSemaphoreCounterValue) { | ||
| 198 | Proc(dld.vkGetSemaphoreCounterValue, dld, "vkGetSemaphoreCounterValueKHR", device); | ||
| 199 | Proc(dld.vkWaitSemaphores, dld, "vkWaitSemaphoresKHR", device); | ||
| 200 | } | ||
| 201 | |||
| 202 | // Support for host query reset is mandatory in Vulkan 1.2 | ||
| 203 | if (!dld.vkResetQueryPool) { | ||
| 204 | Proc(dld.vkResetQueryPool, dld, "vkResetQueryPoolEXT", device); | ||
| 205 | } | ||
| 195 | #undef X | 206 | #undef X |
| 196 | } | 207 | } |
| 197 | 208 | ||
| @@ -224,12 +235,13 @@ bool Load(VkInstance instance, InstanceDispatch& dld) noexcept { | |||
| 224 | X(vkCreateDebugUtilsMessengerEXT); | 235 | X(vkCreateDebugUtilsMessengerEXT); |
| 225 | X(vkDestroyDebugUtilsMessengerEXT); | 236 | X(vkDestroyDebugUtilsMessengerEXT); |
| 226 | X(vkDestroySurfaceKHR); | 237 | X(vkDestroySurfaceKHR); |
| 227 | X(vkGetPhysicalDeviceFeatures2KHR); | 238 | X(vkGetPhysicalDeviceFeatures2); |
| 228 | X(vkGetPhysicalDeviceProperties2KHR); | 239 | X(vkGetPhysicalDeviceProperties2); |
| 229 | X(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); | 240 | X(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); |
| 230 | X(vkGetPhysicalDeviceSurfaceFormatsKHR); | 241 | X(vkGetPhysicalDeviceSurfaceFormatsKHR); |
| 231 | X(vkGetPhysicalDeviceSurfacePresentModesKHR); | 242 | X(vkGetPhysicalDeviceSurfacePresentModesKHR); |
| 232 | X(vkGetPhysicalDeviceSurfaceSupportKHR); | 243 | X(vkGetPhysicalDeviceSurfaceSupportKHR); |
| 244 | X(vkGetPhysicalDeviceToolProperties); | ||
| 233 | X(vkGetSwapchainImagesKHR); | 245 | X(vkGetSwapchainImagesKHR); |
| 234 | X(vkQueuePresentKHR); | 246 | X(vkQueuePresentKHR); |
| 235 | 247 | ||
| @@ -359,9 +371,9 @@ void Destroy(VkDevice device, VkDescriptorSetLayout handle, const DeviceDispatch | |||
| 359 | dld.vkDestroyDescriptorSetLayout(device, handle, nullptr); | 371 | dld.vkDestroyDescriptorSetLayout(device, handle, nullptr); |
| 360 | } | 372 | } |
| 361 | 373 | ||
| 362 | void Destroy(VkDevice device, VkDescriptorUpdateTemplateKHR handle, | 374 | void Destroy(VkDevice device, VkDescriptorUpdateTemplate handle, |
| 363 | const DeviceDispatch& dld) noexcept { | 375 | const DeviceDispatch& dld) noexcept { |
| 364 | dld.vkDestroyDescriptorUpdateTemplateKHR(device, handle, nullptr); | 376 | dld.vkDestroyDescriptorUpdateTemplate(device, handle, nullptr); |
| 365 | } | 377 | } |
| 366 | 378 | ||
| 367 | void Destroy(VkDevice device, VkDeviceMemory handle, const DeviceDispatch& dld) noexcept { | 379 | void Destroy(VkDevice device, VkDeviceMemory handle, const DeviceDispatch& dld) noexcept { |
| @@ -442,6 +454,12 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe | |||
| 442 | 454 | ||
| 443 | Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions, | 455 | Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions, |
| 444 | InstanceDispatch& dispatch) { | 456 | InstanceDispatch& dispatch) { |
| 457 | #ifdef __APPLE__ | ||
| 458 | constexpr VkFlags ci_flags{VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR}; | ||
| 459 | #else | ||
| 460 | constexpr VkFlags ci_flags{}; | ||
| 461 | #endif | ||
| 462 | |||
| 445 | const VkApplicationInfo application_info{ | 463 | const VkApplicationInfo application_info{ |
| 446 | .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, | 464 | .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, |
| 447 | .pNext = nullptr, | 465 | .pNext = nullptr, |
| @@ -454,7 +472,7 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char | |||
| 454 | const VkInstanceCreateInfo ci{ | 472 | const VkInstanceCreateInfo ci{ |
| 455 | .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, | 473 | .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, |
| 456 | .pNext = nullptr, | 474 | .pNext = nullptr, |
| 457 | .flags = 0, | 475 | .flags = ci_flags, |
| 458 | .pApplicationInfo = &application_info, | 476 | .pApplicationInfo = &application_info, |
| 459 | .enabledLayerCount = layers.size(), | 477 | .enabledLayerCount = layers.size(), |
| 460 | .ppEnabledLayerNames = layers.data(), | 478 | .ppEnabledLayerNames = layers.data(), |
| @@ -737,11 +755,11 @@ CommandPool Device::CreateCommandPool(const VkCommandPoolCreateInfo& ci) const { | |||
| 737 | return CommandPool(object, handle, *dld); | 755 | return CommandPool(object, handle, *dld); |
| 738 | } | 756 | } |
| 739 | 757 | ||
| 740 | DescriptorUpdateTemplateKHR Device::CreateDescriptorUpdateTemplateKHR( | 758 | DescriptorUpdateTemplate Device::CreateDescriptorUpdateTemplate( |
| 741 | const VkDescriptorUpdateTemplateCreateInfoKHR& ci) const { | 759 | const VkDescriptorUpdateTemplateCreateInfo& ci) const { |
| 742 | VkDescriptorUpdateTemplateKHR object; | 760 | VkDescriptorUpdateTemplate object; |
| 743 | Check(dld->vkCreateDescriptorUpdateTemplateKHR(handle, &ci, nullptr, &object)); | 761 | Check(dld->vkCreateDescriptorUpdateTemplate(handle, &ci, nullptr, &object)); |
| 744 | return DescriptorUpdateTemplateKHR(object, handle, *dld); | 762 | return DescriptorUpdateTemplate(object, handle, *dld); |
| 745 | } | 763 | } |
| 746 | 764 | ||
| 747 | QueryPool Device::CreateQueryPool(const VkQueryPoolCreateInfo& ci) const { | 765 | QueryPool Device::CreateQueryPool(const VkQueryPoolCreateInfo& ci) const { |
| @@ -857,20 +875,20 @@ VkPhysicalDeviceProperties PhysicalDevice::GetProperties() const noexcept { | |||
| 857 | return properties; | 875 | return properties; |
| 858 | } | 876 | } |
| 859 | 877 | ||
| 860 | void PhysicalDevice::GetProperties2KHR(VkPhysicalDeviceProperties2KHR& properties) const noexcept { | 878 | void PhysicalDevice::GetProperties2(VkPhysicalDeviceProperties2& properties) const noexcept { |
| 861 | dld->vkGetPhysicalDeviceProperties2KHR(physical_device, &properties); | 879 | dld->vkGetPhysicalDeviceProperties2(physical_device, &properties); |
| 862 | } | 880 | } |
| 863 | 881 | ||
| 864 | VkPhysicalDeviceFeatures PhysicalDevice::GetFeatures() const noexcept { | 882 | VkPhysicalDeviceFeatures PhysicalDevice::GetFeatures() const noexcept { |
| 865 | VkPhysicalDeviceFeatures2KHR features2; | 883 | VkPhysicalDeviceFeatures2 features2; |
| 866 | features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR; | 884 | features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; |
| 867 | features2.pNext = nullptr; | 885 | features2.pNext = nullptr; |
| 868 | dld->vkGetPhysicalDeviceFeatures2KHR(physical_device, &features2); | 886 | dld->vkGetPhysicalDeviceFeatures2(physical_device, &features2); |
| 869 | return features2.features; | 887 | return features2.features; |
| 870 | } | 888 | } |
| 871 | 889 | ||
| 872 | void PhysicalDevice::GetFeatures2KHR(VkPhysicalDeviceFeatures2KHR& features) const noexcept { | 890 | void PhysicalDevice::GetFeatures2(VkPhysicalDeviceFeatures2& features) const noexcept { |
| 873 | dld->vkGetPhysicalDeviceFeatures2KHR(physical_device, &features); | 891 | dld->vkGetPhysicalDeviceFeatures2(physical_device, &features); |
| 874 | } | 892 | } |
| 875 | 893 | ||
| 876 | VkFormatProperties PhysicalDevice::GetFormatProperties(VkFormat format) const noexcept { | 894 | VkFormatProperties PhysicalDevice::GetFormatProperties(VkFormat format) const noexcept { |
| @@ -895,6 +913,18 @@ std::vector<VkQueueFamilyProperties> PhysicalDevice::GetQueueFamilyProperties() | |||
| 895 | return properties; | 913 | return properties; |
| 896 | } | 914 | } |
| 897 | 915 | ||
| 916 | std::vector<VkPhysicalDeviceToolProperties> PhysicalDevice::GetPhysicalDeviceToolProperties() | ||
| 917 | const { | ||
| 918 | u32 num = 0; | ||
| 919 | if (!dld->vkGetPhysicalDeviceToolProperties) { | ||
| 920 | return {}; | ||
| 921 | } | ||
| 922 | dld->vkGetPhysicalDeviceToolProperties(physical_device, &num, nullptr); | ||
| 923 | std::vector<VkPhysicalDeviceToolProperties> properties(num); | ||
| 924 | dld->vkGetPhysicalDeviceToolProperties(physical_device, &num, properties.data()); | ||
| 925 | return properties; | ||
| 926 | } | ||
| 927 | |||
| 898 | bool PhysicalDevice::GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR surface) const { | 928 | bool PhysicalDevice::GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR surface) const { |
| 899 | VkBool32 supported; | 929 | VkBool32 supported; |
| 900 | Check(dld->vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_index, surface, | 930 | Check(dld->vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_index, surface, |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h index 1b3f493bd..8395ff2cb 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.h +++ b/src/video_core/vulkan_common/vulkan_wrapper.h | |||
| @@ -168,12 +168,13 @@ struct InstanceDispatch { | |||
| 168 | PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties{}; | 168 | PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties{}; |
| 169 | PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices{}; | 169 | PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices{}; |
| 170 | PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr{}; | 170 | PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr{}; |
| 171 | PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR{}; | 171 | PFN_vkGetPhysicalDeviceFeatures2 vkGetPhysicalDeviceFeatures2{}; |
| 172 | PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties{}; | 172 | PFN_vkGetPhysicalDeviceFormatProperties vkGetPhysicalDeviceFormatProperties{}; |
| 173 | PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties{}; | 173 | PFN_vkGetPhysicalDeviceMemoryProperties vkGetPhysicalDeviceMemoryProperties{}; |
| 174 | PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2{}; | 174 | PFN_vkGetPhysicalDeviceMemoryProperties2 vkGetPhysicalDeviceMemoryProperties2{}; |
| 175 | PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties{}; | 175 | PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties{}; |
| 176 | PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR{}; | 176 | PFN_vkGetPhysicalDeviceProperties2 vkGetPhysicalDeviceProperties2{}; |
| 177 | PFN_vkGetPhysicalDeviceToolProperties vkGetPhysicalDeviceToolProperties{}; | ||
| 177 | PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties{}; | 178 | PFN_vkGetPhysicalDeviceQueueFamilyProperties vkGetPhysicalDeviceQueueFamilyProperties{}; |
| 178 | PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR{}; | 179 | PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR{}; |
| 179 | PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR{}; | 180 | PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR{}; |
| @@ -247,7 +248,7 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 247 | PFN_vkCreateComputePipelines vkCreateComputePipelines{}; | 248 | PFN_vkCreateComputePipelines vkCreateComputePipelines{}; |
| 248 | PFN_vkCreateDescriptorPool vkCreateDescriptorPool{}; | 249 | PFN_vkCreateDescriptorPool vkCreateDescriptorPool{}; |
| 249 | PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout{}; | 250 | PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout{}; |
| 250 | PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR{}; | 251 | PFN_vkCreateDescriptorUpdateTemplate vkCreateDescriptorUpdateTemplate{}; |
| 251 | PFN_vkCreateEvent vkCreateEvent{}; | 252 | PFN_vkCreateEvent vkCreateEvent{}; |
| 252 | PFN_vkCreateFence vkCreateFence{}; | 253 | PFN_vkCreateFence vkCreateFence{}; |
| 253 | PFN_vkCreateFramebuffer vkCreateFramebuffer{}; | 254 | PFN_vkCreateFramebuffer vkCreateFramebuffer{}; |
| @@ -266,7 +267,7 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 266 | PFN_vkDestroyCommandPool vkDestroyCommandPool{}; | 267 | PFN_vkDestroyCommandPool vkDestroyCommandPool{}; |
| 267 | PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool{}; | 268 | PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool{}; |
| 268 | PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout{}; | 269 | PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout{}; |
| 269 | PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR{}; | 270 | PFN_vkDestroyDescriptorUpdateTemplate vkDestroyDescriptorUpdateTemplate{}; |
| 270 | PFN_vkDestroyEvent vkDestroyEvent{}; | 271 | PFN_vkDestroyEvent vkDestroyEvent{}; |
| 271 | PFN_vkDestroyFence vkDestroyFence{}; | 272 | PFN_vkDestroyFence vkDestroyFence{}; |
| 272 | PFN_vkDestroyFramebuffer vkDestroyFramebuffer{}; | 273 | PFN_vkDestroyFramebuffer vkDestroyFramebuffer{}; |
| @@ -297,18 +298,18 @@ struct DeviceDispatch : InstanceDispatch { | |||
| 297 | PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR{}; | 298 | PFN_vkGetPipelineExecutablePropertiesKHR vkGetPipelineExecutablePropertiesKHR{}; |
| 298 | PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{}; | 299 | PFN_vkGetPipelineExecutableStatisticsKHR vkGetPipelineExecutableStatisticsKHR{}; |
| 299 | PFN_vkGetQueryPoolResults vkGetQueryPoolResults{}; | 300 | PFN_vkGetQueryPoolResults vkGetQueryPoolResults{}; |
| 300 | PFN_vkGetSemaphoreCounterValueKHR vkGetSemaphoreCounterValueKHR{}; | 301 | PFN_vkGetSemaphoreCounterValue vkGetSemaphoreCounterValue{}; |
| 301 | PFN_vkMapMemory vkMapMemory{}; | 302 | PFN_vkMapMemory vkMapMemory{}; |
| 302 | PFN_vkQueueSubmit vkQueueSubmit{}; | 303 | PFN_vkQueueSubmit vkQueueSubmit{}; |
| 303 | PFN_vkResetFences vkResetFences{}; | 304 | PFN_vkResetFences vkResetFences{}; |
| 304 | PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT{}; | 305 | PFN_vkResetQueryPool vkResetQueryPool{}; |
| 305 | PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT{}; | 306 | PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT{}; |
| 306 | PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT{}; | 307 | PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT{}; |
| 307 | PFN_vkUnmapMemory vkUnmapMemory{}; | 308 | PFN_vkUnmapMemory vkUnmapMemory{}; |
| 308 | PFN_vkUpdateDescriptorSetWithTemplateKHR vkUpdateDescriptorSetWithTemplateKHR{}; | 309 | PFN_vkUpdateDescriptorSetWithTemplate vkUpdateDescriptorSetWithTemplate{}; |
| 309 | PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{}; | 310 | PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{}; |
| 310 | PFN_vkWaitForFences vkWaitForFences{}; | 311 | PFN_vkWaitForFences vkWaitForFences{}; |
| 311 | PFN_vkWaitSemaphoresKHR vkWaitSemaphoresKHR{}; | 312 | PFN_vkWaitSemaphores vkWaitSemaphores{}; |
| 312 | }; | 313 | }; |
| 313 | 314 | ||
| 314 | /// Loads instance agnostic function pointers. | 315 | /// Loads instance agnostic function pointers. |
| @@ -327,7 +328,7 @@ void Destroy(VkDevice, VkBufferView, const DeviceDispatch&) noexcept; | |||
| 327 | void Destroy(VkDevice, VkCommandPool, const DeviceDispatch&) noexcept; | 328 | void Destroy(VkDevice, VkCommandPool, const DeviceDispatch&) noexcept; |
| 328 | void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept; | 329 | void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept; |
| 329 | void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept; | 330 | void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept; |
| 330 | void Destroy(VkDevice, VkDescriptorUpdateTemplateKHR, const DeviceDispatch&) noexcept; | 331 | void Destroy(VkDevice, VkDescriptorUpdateTemplate, const DeviceDispatch&) noexcept; |
| 331 | void Destroy(VkDevice, VkDeviceMemory, const DeviceDispatch&) noexcept; | 332 | void Destroy(VkDevice, VkDeviceMemory, const DeviceDispatch&) noexcept; |
| 332 | void Destroy(VkDevice, VkEvent, const DeviceDispatch&) noexcept; | 333 | void Destroy(VkDevice, VkEvent, const DeviceDispatch&) noexcept; |
| 333 | void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept; | 334 | void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept; |
| @@ -559,7 +560,7 @@ private: | |||
| 559 | 560 | ||
| 560 | using DebugUtilsMessenger = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>; | 561 | using DebugUtilsMessenger = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>; |
| 561 | using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>; | 562 | using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>; |
| 562 | using DescriptorUpdateTemplateKHR = Handle<VkDescriptorUpdateTemplateKHR, VkDevice, DeviceDispatch>; | 563 | using DescriptorUpdateTemplate = Handle<VkDescriptorUpdateTemplate, VkDevice, DeviceDispatch>; |
| 563 | using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>; | 564 | using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>; |
| 564 | using PipelineLayout = Handle<VkPipelineLayout, VkDevice, DeviceDispatch>; | 565 | using PipelineLayout = Handle<VkPipelineLayout, VkDevice, DeviceDispatch>; |
| 565 | using QueryPool = Handle<VkQueryPool, VkDevice, DeviceDispatch>; | 566 | using QueryPool = Handle<VkQueryPool, VkDevice, DeviceDispatch>; |
| @@ -766,7 +767,7 @@ public: | |||
| 766 | 767 | ||
| 767 | [[nodiscard]] u64 GetCounter() const { | 768 | [[nodiscard]] u64 GetCounter() const { |
| 768 | u64 value; | 769 | u64 value; |
| 769 | Check(dld->vkGetSemaphoreCounterValueKHR(owner, handle, &value)); | 770 | Check(dld->vkGetSemaphoreCounterValue(owner, handle, &value)); |
| 770 | return value; | 771 | return value; |
| 771 | } | 772 | } |
| 772 | 773 | ||
| @@ -778,15 +779,15 @@ public: | |||
| 778 | * @return True on successful wait, false on timeout | 779 | * @return True on successful wait, false on timeout |
| 779 | */ | 780 | */ |
| 780 | bool Wait(u64 value, u64 timeout = std::numeric_limits<u64>::max()) const { | 781 | bool Wait(u64 value, u64 timeout = std::numeric_limits<u64>::max()) const { |
| 781 | const VkSemaphoreWaitInfoKHR wait_info{ | 782 | const VkSemaphoreWaitInfo wait_info{ |
| 782 | .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO_KHR, | 783 | .sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO, |
| 783 | .pNext = nullptr, | 784 | .pNext = nullptr, |
| 784 | .flags = 0, | 785 | .flags = 0, |
| 785 | .semaphoreCount = 1, | 786 | .semaphoreCount = 1, |
| 786 | .pSemaphores = &handle, | 787 | .pSemaphores = &handle, |
| 787 | .pValues = &value, | 788 | .pValues = &value, |
| 788 | }; | 789 | }; |
| 789 | const VkResult result = dld->vkWaitSemaphoresKHR(owner, &wait_info, timeout); | 790 | const VkResult result = dld->vkWaitSemaphores(owner, &wait_info, timeout); |
| 790 | switch (result) { | 791 | switch (result) { |
| 791 | case VK_SUCCESS: | 792 | case VK_SUCCESS: |
| 792 | return true; | 793 | return true; |
| @@ -840,8 +841,8 @@ public: | |||
| 840 | 841 | ||
| 841 | CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const; | 842 | CommandPool CreateCommandPool(const VkCommandPoolCreateInfo& ci) const; |
| 842 | 843 | ||
| 843 | DescriptorUpdateTemplateKHR CreateDescriptorUpdateTemplateKHR( | 844 | DescriptorUpdateTemplate CreateDescriptorUpdateTemplate( |
| 844 | const VkDescriptorUpdateTemplateCreateInfoKHR& ci) const; | 845 | const VkDescriptorUpdateTemplateCreateInfo& ci) const; |
| 845 | 846 | ||
| 846 | QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const; | 847 | QueryPool CreateQueryPool(const VkQueryPoolCreateInfo& ci) const; |
| 847 | 848 | ||
| @@ -869,9 +870,9 @@ public: | |||
| 869 | void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes, | 870 | void UpdateDescriptorSets(Span<VkWriteDescriptorSet> writes, |
| 870 | Span<VkCopyDescriptorSet> copies) const noexcept; | 871 | Span<VkCopyDescriptorSet> copies) const noexcept; |
| 871 | 872 | ||
| 872 | void UpdateDescriptorSet(VkDescriptorSet set, VkDescriptorUpdateTemplateKHR update_template, | 873 | void UpdateDescriptorSet(VkDescriptorSet set, VkDescriptorUpdateTemplate update_template, |
| 873 | const void* data) const noexcept { | 874 | const void* data) const noexcept { |
| 874 | dld->vkUpdateDescriptorSetWithTemplateKHR(handle, set, update_template, data); | 875 | dld->vkUpdateDescriptorSetWithTemplate(handle, set, update_template, data); |
| 875 | } | 876 | } |
| 876 | 877 | ||
| 877 | VkResult AcquireNextImageKHR(VkSwapchainKHR swapchain, u64 timeout, VkSemaphore semaphore, | 878 | VkResult AcquireNextImageKHR(VkSwapchainKHR swapchain, u64 timeout, VkSemaphore semaphore, |
| @@ -884,8 +885,8 @@ public: | |||
| 884 | return dld->vkDeviceWaitIdle(handle); | 885 | return dld->vkDeviceWaitIdle(handle); |
| 885 | } | 886 | } |
| 886 | 887 | ||
| 887 | void ResetQueryPoolEXT(VkQueryPool query_pool, u32 first, u32 count) const noexcept { | 888 | void ResetQueryPool(VkQueryPool query_pool, u32 first, u32 count) const noexcept { |
| 888 | dld->vkResetQueryPoolEXT(handle, query_pool, first, count); | 889 | dld->vkResetQueryPool(handle, query_pool, first, count); |
| 889 | } | 890 | } |
| 890 | 891 | ||
| 891 | VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size, | 892 | VkResult GetQueryResults(VkQueryPool query_pool, u32 first, u32 count, std::size_t data_size, |
| @@ -910,11 +911,11 @@ public: | |||
| 910 | 911 | ||
| 911 | VkPhysicalDeviceProperties GetProperties() const noexcept; | 912 | VkPhysicalDeviceProperties GetProperties() const noexcept; |
| 912 | 913 | ||
| 913 | void GetProperties2KHR(VkPhysicalDeviceProperties2KHR&) const noexcept; | 914 | void GetProperties2(VkPhysicalDeviceProperties2&) const noexcept; |
| 914 | 915 | ||
| 915 | VkPhysicalDeviceFeatures GetFeatures() const noexcept; | 916 | VkPhysicalDeviceFeatures GetFeatures() const noexcept; |
| 916 | 917 | ||
| 917 | void GetFeatures2KHR(VkPhysicalDeviceFeatures2KHR&) const noexcept; | 918 | void GetFeatures2(VkPhysicalDeviceFeatures2&) const noexcept; |
| 918 | 919 | ||
| 919 | VkFormatProperties GetFormatProperties(VkFormat) const noexcept; | 920 | VkFormatProperties GetFormatProperties(VkFormat) const noexcept; |
| 920 | 921 | ||
| @@ -922,6 +923,8 @@ public: | |||
| 922 | 923 | ||
| 923 | std::vector<VkQueueFamilyProperties> GetQueueFamilyProperties() const; | 924 | std::vector<VkQueueFamilyProperties> GetQueueFamilyProperties() const; |
| 924 | 925 | ||
| 926 | std::vector<VkPhysicalDeviceToolProperties> GetPhysicalDeviceToolProperties() const; | ||
| 927 | |||
| 925 | bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const; | 928 | bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const; |
| 926 | 929 | ||
| 927 | VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const; | 930 | VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const; |
| @@ -980,7 +983,7 @@ public: | |||
| 980 | dynamic_offsets.size(), dynamic_offsets.data()); | 983 | dynamic_offsets.size(), dynamic_offsets.data()); |
| 981 | } | 984 | } |
| 982 | 985 | ||
| 983 | void PushDescriptorSetWithTemplateKHR(VkDescriptorUpdateTemplateKHR update_template, | 986 | void PushDescriptorSetWithTemplateKHR(VkDescriptorUpdateTemplate update_template, |
| 984 | VkPipelineLayout layout, u32 set, | 987 | VkPipelineLayout layout, u32 set, |
| 985 | const void* data) const noexcept { | 988 | const void* data) const noexcept { |
| 986 | dld->vkCmdPushDescriptorSetWithTemplateKHR(handle, update_template, layout, set, data); | 989 | dld->vkCmdPushDescriptorSetWithTemplateKHR(handle, update_template, layout, set, data); |
diff --git a/src/web_service/CMakeLists.txt b/src/web_service/CMakeLists.txt index 3f75d97d1..02582aa04 100644 --- a/src/web_service/CMakeLists.txt +++ b/src/web_service/CMakeLists.txt | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | add_library(web_service STATIC | 4 | add_library(web_service STATIC |
| 5 | announce_room_json.cpp | 5 | announce_room_json.cpp |
| 6 | announce_room_json.h | 6 | announce_room_json.h |
| 7 | precompiled_headers.h | ||
| 7 | telemetry_json.cpp | 8 | telemetry_json.cpp |
| 8 | telemetry_json.h | 9 | telemetry_json.h |
| 9 | verify_login.cpp | 10 | verify_login.cpp |
| @@ -16,4 +17,8 @@ add_library(web_service STATIC | |||
| 16 | ) | 17 | ) |
| 17 | 18 | ||
| 18 | create_target_directory_groups(web_service) | 19 | create_target_directory_groups(web_service) |
| 19 | target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib cpp-jwt) | 20 | target_link_libraries(web_service PRIVATE common network nlohmann_json::nlohmann_json httplib::httplib cpp-jwt::cpp-jwt) |
| 21 | |||
| 22 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 23 | target_precompile_headers(web_service PRIVATE precompiled_headers.h) | ||
| 24 | endif() | ||
diff --git a/src/web_service/precompiled_headers.h b/src/web_service/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/web_service/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 060de0259..d23eb2907 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -88,6 +88,9 @@ add_executable(yuzu | |||
| 88 | configuration/configure_input_advanced.cpp | 88 | configuration/configure_input_advanced.cpp |
| 89 | configuration/configure_input_advanced.h | 89 | configuration/configure_input_advanced.h |
| 90 | configuration/configure_input_advanced.ui | 90 | configuration/configure_input_advanced.ui |
| 91 | configuration/configure_input_per_game.cpp | ||
| 92 | configuration/configure_input_per_game.h | ||
| 93 | configuration/configure_input_per_game.ui | ||
| 91 | configuration/configure_input_player.cpp | 94 | configuration/configure_input_player.cpp |
| 92 | configuration/configure_input_player.h | 95 | configuration/configure_input_player.h |
| 93 | configuration/configure_input_player.ui | 96 | configuration/configure_input_player.ui |
| @@ -186,6 +189,7 @@ add_executable(yuzu | |||
| 186 | multiplayer/state.cpp | 189 | multiplayer/state.cpp |
| 187 | multiplayer/state.h | 190 | multiplayer/state.h |
| 188 | multiplayer/validation.h | 191 | multiplayer/validation.h |
| 192 | precompiled_headers.h | ||
| 189 | startup_checks.cpp | 193 | startup_checks.cpp |
| 190 | startup_checks.h | 194 | startup_checks.h |
| 191 | uisettings.cpp | 195 | uisettings.cpp |
| @@ -314,7 +318,7 @@ target_link_libraries(yuzu PRIVATE common core input_common network video_core) | |||
| 314 | target_link_libraries(yuzu PRIVATE Boost::boost glad Qt${QT_MAJOR_VERSION}::Widgets) | 318 | target_link_libraries(yuzu PRIVATE Boost::boost glad Qt${QT_MAJOR_VERSION}::Widgets) |
| 315 | target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) | 319 | target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) |
| 316 | 320 | ||
| 317 | target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) | 321 | target_link_libraries(yuzu PRIVATE Vulkan::Headers) |
| 318 | if (NOT WIN32) | 322 | if (NOT WIN32) |
| 319 | target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS}) | 323 | target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS}) |
| 320 | endif() | 324 | endif() |
| @@ -350,7 +354,7 @@ if (USE_DISCORD_PRESENCE) | |||
| 350 | discord_impl.cpp | 354 | discord_impl.cpp |
| 351 | discord_impl.h | 355 | discord_impl.h |
| 352 | ) | 356 | ) |
| 353 | target_link_libraries(yuzu PRIVATE discord-rpc) | 357 | target_link_libraries(yuzu PRIVATE DiscordRPC::discord-rpc) |
| 354 | target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE) | 358 | target_compile_definitions(yuzu PRIVATE -DUSE_DISCORD_PRESENCE) |
| 355 | endif() | 359 | endif() |
| 356 | 360 | ||
| @@ -387,11 +391,7 @@ if (YUZU_USE_BUNDLED_QT AND QT_VERSION VERSION_LESS 6) | |||
| 387 | endif() | 391 | endif() |
| 388 | 392 | ||
| 389 | if (ENABLE_SDL2) | 393 | if (ENABLE_SDL2) |
| 390 | if (YUZU_USE_EXTERNAL_SDL2) | 394 | target_link_libraries(yuzu PRIVATE SDL2::SDL2) |
| 391 | target_link_libraries(yuzu PRIVATE SDL2-static) | ||
| 392 | else() | ||
| 393 | target_link_libraries(yuzu PRIVATE SDL2) | ||
| 394 | endif() | ||
| 395 | target_compile_definitions(yuzu PRIVATE HAVE_SDL2) | 395 | target_compile_definitions(yuzu PRIVATE HAVE_SDL2) |
| 396 | endif() | 396 | endif() |
| 397 | 397 | ||
| @@ -407,5 +407,9 @@ if (NOT APPLE) | |||
| 407 | endif() | 407 | endif() |
| 408 | 408 | ||
| 409 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) | 409 | if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) |
| 410 | target_link_libraries(yuzu PRIVATE dynarmic) | 410 | target_link_libraries(yuzu PRIVATE dynarmic::dynarmic) |
| 411 | endif() | ||
| 412 | |||
| 413 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 414 | target_precompile_headers(yuzu PRIVATE precompiled_headers.h) | ||
| 411 | endif() | 415 | endif() |
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp index 12efdc216..c30b54499 100644 --- a/src/yuzu/applets/qt_controller.cpp +++ b/src/yuzu/applets/qt_controller.cpp | |||
| @@ -685,7 +685,7 @@ QtControllerSelector::QtControllerSelector(GMainWindow& parent) { | |||
| 685 | QtControllerSelector::~QtControllerSelector() = default; | 685 | QtControllerSelector::~QtControllerSelector() = default; |
| 686 | 686 | ||
| 687 | void QtControllerSelector::ReconfigureControllers( | 687 | void QtControllerSelector::ReconfigureControllers( |
| 688 | std::function<void()> callback_, const Core::Frontend::ControllerParameters& parameters) const { | 688 | ReconfigureCallback callback_, const Core::Frontend::ControllerParameters& parameters) const { |
| 689 | callback = std::move(callback_); | 689 | callback = std::move(callback_); |
| 690 | emit MainWindowReconfigureControllers(parameters); | 690 | emit MainWindowReconfigureControllers(parameters); |
| 691 | } | 691 | } |
diff --git a/src/yuzu/applets/qt_controller.h b/src/yuzu/applets/qt_controller.h index cf948d2b5..16e99f507 100644 --- a/src/yuzu/applets/qt_controller.h +++ b/src/yuzu/applets/qt_controller.h | |||
| @@ -157,7 +157,7 @@ public: | |||
| 157 | ~QtControllerSelector() override; | 157 | ~QtControllerSelector() override; |
| 158 | 158 | ||
| 159 | void ReconfigureControllers( | 159 | void ReconfigureControllers( |
| 160 | std::function<void()> callback_, | 160 | ReconfigureCallback callback_, |
| 161 | const Core::Frontend::ControllerParameters& parameters) const override; | 161 | const Core::Frontend::ControllerParameters& parameters) const override; |
| 162 | 162 | ||
| 163 | signals: | 163 | signals: |
| @@ -167,5 +167,5 @@ signals: | |||
| 167 | private: | 167 | private: |
| 168 | void MainWindowReconfigureFinished(); | 168 | void MainWindowReconfigureFinished(); |
| 169 | 169 | ||
| 170 | mutable std::function<void()> callback; | 170 | mutable ReconfigureCallback callback; |
| 171 | }; | 171 | }; |
diff --git a/src/yuzu/applets/qt_error.cpp b/src/yuzu/applets/qt_error.cpp index 367d5352d..e0190a979 100644 --- a/src/yuzu/applets/qt_error.cpp +++ b/src/yuzu/applets/qt_error.cpp | |||
| @@ -14,7 +14,7 @@ QtErrorDisplay::QtErrorDisplay(GMainWindow& parent) { | |||
| 14 | 14 | ||
| 15 | QtErrorDisplay::~QtErrorDisplay() = default; | 15 | QtErrorDisplay::~QtErrorDisplay() = default; |
| 16 | 16 | ||
| 17 | void QtErrorDisplay::ShowError(Result error, std::function<void()> finished) const { | 17 | void QtErrorDisplay::ShowError(Result error, FinishedCallback finished) const { |
| 18 | callback = std::move(finished); | 18 | callback = std::move(finished); |
| 19 | emit MainWindowDisplayError( | 19 | emit MainWindowDisplayError( |
| 20 | tr("Error Code: %1-%2 (0x%3)") | 20 | tr("Error Code: %1-%2 (0x%3)") |
| @@ -25,7 +25,7 @@ void QtErrorDisplay::ShowError(Result error, std::function<void()> finished) con | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds time, | 27 | void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds time, |
| 28 | std::function<void()> finished) const { | 28 | FinishedCallback finished) const { |
| 29 | callback = std::move(finished); | 29 | callback = std::move(finished); |
| 30 | 30 | ||
| 31 | const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); | 31 | const QDateTime date_time = QDateTime::fromSecsSinceEpoch(time.count()); |
| @@ -42,7 +42,7 @@ void QtErrorDisplay::ShowErrorWithTimestamp(Result error, std::chrono::seconds t | |||
| 42 | 42 | ||
| 43 | void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text, | 43 | void QtErrorDisplay::ShowCustomErrorText(Result error, std::string dialog_text, |
| 44 | std::string fullscreen_text, | 44 | std::string fullscreen_text, |
| 45 | std::function<void()> finished) const { | 45 | FinishedCallback finished) const { |
| 46 | callback = std::move(finished); | 46 | callback = std::move(finished); |
| 47 | emit MainWindowDisplayError( | 47 | emit MainWindowDisplayError( |
| 48 | tr("Error Code: %1-%2 (0x%3)") | 48 | tr("Error Code: %1-%2 (0x%3)") |
diff --git a/src/yuzu/applets/qt_error.h b/src/yuzu/applets/qt_error.h index eb4107c7e..e4e174721 100644 --- a/src/yuzu/applets/qt_error.h +++ b/src/yuzu/applets/qt_error.h | |||
| @@ -16,11 +16,11 @@ public: | |||
| 16 | explicit QtErrorDisplay(GMainWindow& parent); | 16 | explicit QtErrorDisplay(GMainWindow& parent); |
| 17 | ~QtErrorDisplay() override; | 17 | ~QtErrorDisplay() override; |
| 18 | 18 | ||
| 19 | void ShowError(Result error, std::function<void()> finished) const override; | 19 | void ShowError(Result error, FinishedCallback finished) const override; |
| 20 | void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, | 20 | void ShowErrorWithTimestamp(Result error, std::chrono::seconds time, |
| 21 | std::function<void()> finished) const override; | 21 | FinishedCallback finished) const override; |
| 22 | void ShowCustomErrorText(Result error, std::string dialog_text, std::string fullscreen_text, | 22 | void ShowCustomErrorText(Result error, std::string dialog_text, std::string fullscreen_text, |
| 23 | std::function<void()> finished) const override; | 23 | FinishedCallback finished) const override; |
| 24 | 24 | ||
| 25 | signals: | 25 | signals: |
| 26 | void MainWindowDisplayError(QString error_code, QString error_text) const; | 26 | void MainWindowDisplayError(QString error_code, QString error_text) const; |
| @@ -28,5 +28,5 @@ signals: | |||
| 28 | private: | 28 | private: |
| 29 | void MainWindowFinishedError(); | 29 | void MainWindowFinishedError(); |
| 30 | 30 | ||
| 31 | mutable std::function<void()> callback; | 31 | mutable FinishedCallback callback; |
| 32 | }; | 32 | }; |
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp index c8bcfb223..4145c5299 100644 --- a/src/yuzu/applets/qt_profile_select.cpp +++ b/src/yuzu/applets/qt_profile_select.cpp | |||
| @@ -163,8 +163,7 @@ QtProfileSelector::QtProfileSelector(GMainWindow& parent) { | |||
| 163 | 163 | ||
| 164 | QtProfileSelector::~QtProfileSelector() = default; | 164 | QtProfileSelector::~QtProfileSelector() = default; |
| 165 | 165 | ||
| 166 | void QtProfileSelector::SelectProfile( | 166 | void QtProfileSelector::SelectProfile(SelectProfileCallback callback_) const { |
| 167 | std::function<void(std::optional<Common::UUID>)> callback_) const { | ||
| 168 | callback = std::move(callback_); | 167 | callback = std::move(callback_); |
| 169 | emit MainWindowSelectProfile(); | 168 | emit MainWindowSelectProfile(); |
| 170 | } | 169 | } |
diff --git a/src/yuzu/applets/qt_profile_select.h b/src/yuzu/applets/qt_profile_select.h index 124f2cdbd..637a3bda2 100644 --- a/src/yuzu/applets/qt_profile_select.h +++ b/src/yuzu/applets/qt_profile_select.h | |||
| @@ -65,7 +65,7 @@ public: | |||
| 65 | explicit QtProfileSelector(GMainWindow& parent); | 65 | explicit QtProfileSelector(GMainWindow& parent); |
| 66 | ~QtProfileSelector() override; | 66 | ~QtProfileSelector() override; |
| 67 | 67 | ||
| 68 | void SelectProfile(std::function<void(std::optional<Common::UUID>)> callback_) const override; | 68 | void SelectProfile(SelectProfileCallback callback_) const override; |
| 69 | 69 | ||
| 70 | signals: | 70 | signals: |
| 71 | void MainWindowSelectProfile() const; | 71 | void MainWindowSelectProfile() const; |
| @@ -73,5 +73,5 @@ signals: | |||
| 73 | private: | 73 | private: |
| 74 | void MainWindowFinishedSelection(std::optional<Common::UUID> uuid); | 74 | void MainWindowFinishedSelection(std::optional<Common::UUID> uuid); |
| 75 | 75 | ||
| 76 | mutable std::function<void(std::optional<Common::UUID>)> callback; | 76 | mutable SelectProfileCallback callback; |
| 77 | }; | 77 | }; |
diff --git a/src/yuzu/applets/qt_software_keyboard.cpp b/src/yuzu/applets/qt_software_keyboard.cpp index e60506197..734b0ea40 100644 --- a/src/yuzu/applets/qt_software_keyboard.cpp +++ b/src/yuzu/applets/qt_software_keyboard.cpp | |||
| @@ -1566,10 +1566,7 @@ QtSoftwareKeyboard::~QtSoftwareKeyboard() = default; | |||
| 1566 | 1566 | ||
| 1567 | void QtSoftwareKeyboard::InitializeKeyboard( | 1567 | void QtSoftwareKeyboard::InitializeKeyboard( |
| 1568 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, | 1568 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, |
| 1569 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> | 1569 | SubmitNormalCallback submit_normal_callback_, SubmitInlineCallback submit_inline_callback_) { |
| 1570 | submit_normal_callback_, | ||
| 1571 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 1572 | submit_inline_callback_) { | ||
| 1573 | if (is_inline) { | 1570 | if (is_inline) { |
| 1574 | submit_inline_callback = std::move(submit_inline_callback_); | 1571 | submit_inline_callback = std::move(submit_inline_callback_); |
| 1575 | } else { | 1572 | } else { |
diff --git a/src/yuzu/applets/qt_software_keyboard.h b/src/yuzu/applets/qt_software_keyboard.h index 35d4ee2ef..30ac8ecf6 100644 --- a/src/yuzu/applets/qt_software_keyboard.h +++ b/src/yuzu/applets/qt_software_keyboard.h | |||
| @@ -233,12 +233,10 @@ public: | |||
| 233 | explicit QtSoftwareKeyboard(GMainWindow& parent); | 233 | explicit QtSoftwareKeyboard(GMainWindow& parent); |
| 234 | ~QtSoftwareKeyboard() override; | 234 | ~QtSoftwareKeyboard() override; |
| 235 | 235 | ||
| 236 | void InitializeKeyboard( | 236 | void InitializeKeyboard(bool is_inline, |
| 237 | bool is_inline, Core::Frontend::KeyboardInitializeParameters initialize_parameters, | 237 | Core::Frontend::KeyboardInitializeParameters initialize_parameters, |
| 238 | std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> | 238 | SubmitNormalCallback submit_normal_callback_, |
| 239 | submit_normal_callback_, | 239 | SubmitInlineCallback submit_inline_callback_) override; |
| 240 | std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 241 | submit_inline_callback_) override; | ||
| 242 | 240 | ||
| 243 | void ShowNormalKeyboard() const override; | 241 | void ShowNormalKeyboard() const override; |
| 244 | 242 | ||
| @@ -279,8 +277,6 @@ private: | |||
| 279 | void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, | 277 | void SubmitInlineText(Service::AM::Applets::SwkbdReplyType reply_type, |
| 280 | std::u16string submitted_text, s32 cursor_position) const; | 278 | std::u16string submitted_text, s32 cursor_position) const; |
| 281 | 279 | ||
| 282 | mutable std::function<void(Service::AM::Applets::SwkbdResult, std::u16string, bool)> | 280 | mutable SubmitNormalCallback submit_normal_callback; |
| 283 | submit_normal_callback; | 281 | mutable SubmitInlineCallback submit_inline_callback; |
| 284 | mutable std::function<void(Service::AM::Applets::SwkbdReplyType, std::u16string, s32)> | ||
| 285 | submit_inline_callback; | ||
| 286 | }; | 282 | }; |
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp index 89bd482e0..0a5912326 100644 --- a/src/yuzu/applets/qt_web_browser.cpp +++ b/src/yuzu/applets/qt_web_browser.cpp | |||
| @@ -401,9 +401,9 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { | |||
| 401 | 401 | ||
| 402 | QtWebBrowser::~QtWebBrowser() = default; | 402 | QtWebBrowser::~QtWebBrowser() = default; |
| 403 | 403 | ||
| 404 | void QtWebBrowser::OpenLocalWebPage( | 404 | void QtWebBrowser::OpenLocalWebPage(const std::string& local_url, |
| 405 | const std::string& local_url, std::function<void()> extract_romfs_callback_, | 405 | ExtractROMFSCallback extract_romfs_callback_, |
| 406 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { | 406 | OpenWebPageCallback callback_) const { |
| 407 | extract_romfs_callback = std::move(extract_romfs_callback_); | 407 | extract_romfs_callback = std::move(extract_romfs_callback_); |
| 408 | callback = std::move(callback_); | 408 | callback = std::move(callback_); |
| 409 | 409 | ||
| @@ -416,9 +416,8 @@ void QtWebBrowser::OpenLocalWebPage( | |||
| 416 | } | 416 | } |
| 417 | } | 417 | } |
| 418 | 418 | ||
| 419 | void QtWebBrowser::OpenExternalWebPage( | 419 | void QtWebBrowser::OpenExternalWebPage(const std::string& external_url, |
| 420 | const std::string& external_url, | 420 | OpenWebPageCallback callback_) const { |
| 421 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const { | ||
| 422 | callback = std::move(callback_); | 421 | callback = std::move(callback_); |
| 423 | 422 | ||
| 424 | const auto index = external_url.find('?'); | 423 | const auto index = external_url.find('?'); |
diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h index 043800853..e8fe511ed 100644 --- a/src/yuzu/applets/qt_web_browser.h +++ b/src/yuzu/applets/qt_web_browser.h | |||
| @@ -197,13 +197,11 @@ public: | |||
| 197 | ~QtWebBrowser() override; | 197 | ~QtWebBrowser() override; |
| 198 | 198 | ||
| 199 | void OpenLocalWebPage(const std::string& local_url, | 199 | void OpenLocalWebPage(const std::string& local_url, |
| 200 | std::function<void()> extract_romfs_callback_, | 200 | ExtractROMFSCallback extract_romfs_callback_, |
| 201 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | 201 | OpenWebPageCallback callback_) const override; |
| 202 | callback_) const override; | ||
| 203 | 202 | ||
| 204 | void OpenExternalWebPage(const std::string& external_url, | 203 | void OpenExternalWebPage(const std::string& external_url, |
| 205 | std::function<void(Service::AM::Applets::WebExitReason, std::string)> | 204 | OpenWebPageCallback callback_) const override; |
| 206 | callback_) const override; | ||
| 207 | 205 | ||
| 208 | signals: | 206 | signals: |
| 209 | void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args, | 207 | void MainWindowOpenWebPage(const std::string& main_url, const std::string& additional_args, |
| @@ -215,7 +213,6 @@ private: | |||
| 215 | void MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, | 213 | void MainWindowWebBrowserClosed(Service::AM::Applets::WebExitReason exit_reason, |
| 216 | std::string last_url); | 214 | std::string last_url); |
| 217 | 215 | ||
| 218 | mutable std::function<void()> extract_romfs_callback; | 216 | mutable ExtractROMFSCallback extract_romfs_callback; |
| 219 | 217 | mutable OpenWebPageCallback callback; | |
| 220 | mutable std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback; | ||
| 221 | }; | 218 | }; |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index c934069dd..5b5b6fed8 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -118,7 +118,7 @@ void EmuThread::run() { | |||
| 118 | } | 118 | } |
| 119 | } else { | 119 | } else { |
| 120 | std::unique_lock lock{running_mutex}; | 120 | std::unique_lock lock{running_mutex}; |
| 121 | running_cv.wait(lock, stop_token, [this] { return IsRunning(); }); | 121 | Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); }); |
| 122 | } | 122 | } |
| 123 | } | 123 | } |
| 124 | 124 | ||
| @@ -237,8 +237,7 @@ private: | |||
| 237 | GRenderWindow* render_window; | 237 | GRenderWindow* render_window; |
| 238 | }; | 238 | }; |
| 239 | 239 | ||
| 240 | class OpenGLRenderWidget : public RenderWidget { | 240 | struct OpenGLRenderWidget : public RenderWidget { |
| 241 | public: | ||
| 242 | explicit OpenGLRenderWidget(GRenderWindow* parent) : RenderWidget(parent) { | 241 | explicit OpenGLRenderWidget(GRenderWindow* parent) : RenderWidget(parent) { |
| 243 | windowHandle()->setSurfaceType(QWindow::OpenGLSurface); | 242 | windowHandle()->setSurfaceType(QWindow::OpenGLSurface); |
| 244 | } | 243 | } |
| @@ -251,13 +250,16 @@ private: | |||
| 251 | std::unique_ptr<Core::Frontend::GraphicsContext> context; | 250 | std::unique_ptr<Core::Frontend::GraphicsContext> context; |
| 252 | }; | 251 | }; |
| 253 | 252 | ||
| 254 | class VulkanRenderWidget : public RenderWidget { | 253 | struct VulkanRenderWidget : public RenderWidget { |
| 255 | public: | ||
| 256 | explicit VulkanRenderWidget(GRenderWindow* parent) : RenderWidget(parent) { | 254 | explicit VulkanRenderWidget(GRenderWindow* parent) : RenderWidget(parent) { |
| 257 | windowHandle()->setSurfaceType(QWindow::VulkanSurface); | 255 | windowHandle()->setSurfaceType(QWindow::VulkanSurface); |
| 258 | } | 256 | } |
| 259 | }; | 257 | }; |
| 260 | 258 | ||
| 259 | struct NullRenderWidget : public RenderWidget { | ||
| 260 | explicit NullRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {} | ||
| 261 | }; | ||
| 262 | |||
| 261 | static Core::Frontend::WindowSystemType GetWindowSystemType() { | 263 | static Core::Frontend::WindowSystemType GetWindowSystemType() { |
| 262 | // Determine WSI type based on Qt platform. | 264 | // Determine WSI type based on Qt platform. |
| 263 | QString platform_name = QGuiApplication::platformName(); | 265 | QString platform_name = QGuiApplication::platformName(); |
| @@ -267,6 +269,10 @@ static Core::Frontend::WindowSystemType GetWindowSystemType() { | |||
| 267 | return Core::Frontend::WindowSystemType::X11; | 269 | return Core::Frontend::WindowSystemType::X11; |
| 268 | else if (platform_name == QStringLiteral("wayland")) | 270 | else if (platform_name == QStringLiteral("wayland")) |
| 269 | return Core::Frontend::WindowSystemType::Wayland; | 271 | return Core::Frontend::WindowSystemType::Wayland; |
| 272 | else if (platform_name == QStringLiteral("cocoa")) | ||
| 273 | return Core::Frontend::WindowSystemType::Cocoa; | ||
| 274 | else if (platform_name == QStringLiteral("android")) | ||
| 275 | return Core::Frontend::WindowSystemType::Android; | ||
| 270 | 276 | ||
| 271 | LOG_CRITICAL(Frontend, "Unknown Qt platform!"); | 277 | LOG_CRITICAL(Frontend, "Unknown Qt platform!"); |
| 272 | return Core::Frontend::WindowSystemType::Windows; | 278 | return Core::Frontend::WindowSystemType::Windows; |
| @@ -874,6 +880,9 @@ bool GRenderWindow::InitRenderTarget() { | |||
| 874 | return false; | 880 | return false; |
| 875 | } | 881 | } |
| 876 | break; | 882 | break; |
| 883 | case Settings::RendererBackend::Null: | ||
| 884 | InitializeNull(); | ||
| 885 | break; | ||
| 877 | } | 886 | } |
| 878 | 887 | ||
| 879 | // Update the Window System information with the new render target | 888 | // Update the Window System information with the new render target |
| @@ -970,6 +979,11 @@ bool GRenderWindow::InitializeVulkan() { | |||
| 970 | return true; | 979 | return true; |
| 971 | } | 980 | } |
| 972 | 981 | ||
| 982 | void GRenderWindow::InitializeNull() { | ||
| 983 | child_widget = new NullRenderWidget(this); | ||
| 984 | main_context = std::make_unique<DummyContext>(); | ||
| 985 | } | ||
| 986 | |||
| 973 | bool GRenderWindow::LoadOpenGL() { | 987 | bool GRenderWindow::LoadOpenGL() { |
| 974 | auto context = CreateSharedContext(); | 988 | auto context = CreateSharedContext(); |
| 975 | auto scope = context->Acquire(); | 989 | auto scope = context->Acquire(); |
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 4a01481cd..f4deae4ee 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <QTouchEvent> | 14 | #include <QTouchEvent> |
| 15 | #include <QWidget> | 15 | #include <QWidget> |
| 16 | 16 | ||
| 17 | #include "common/polyfill_thread.h" | ||
| 17 | #include "common/thread.h" | 18 | #include "common/thread.h" |
| 18 | #include "core/frontend/emu_window.h" | 19 | #include "core/frontend/emu_window.h" |
| 19 | 20 | ||
| @@ -218,6 +219,7 @@ private: | |||
| 218 | 219 | ||
| 219 | bool InitializeOpenGL(); | 220 | bool InitializeOpenGL(); |
| 220 | bool InitializeVulkan(); | 221 | bool InitializeVulkan(); |
| 222 | void InitializeNull(); | ||
| 221 | bool LoadOpenGL(); | 223 | bool LoadOpenGL(); |
| 222 | QStringList GetUnsupportedGLExtensions() const; | 224 | QStringList GetUnsupportedGLExtensions() const; |
| 223 | 225 | ||
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 0c93df428..722fc708e 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -124,6 +124,10 @@ void Config::Initialize(const std::string& config_name) { | |||
| 124 | } | 124 | } |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | bool Config::IsCustomConfig() { | ||
| 128 | return type == ConfigType::PerGameConfig; | ||
| 129 | } | ||
| 130 | |||
| 127 | /* {Read,Write}BasicSetting and WriteGlobalSetting templates must be defined here before their | 131 | /* {Read,Write}BasicSetting and WriteGlobalSetting templates must be defined here before their |
| 128 | * usages later in this file. This allows explicit definition of some types that don't work | 132 | * usages later in this file. This allows explicit definition of some types that don't work |
| 129 | * nicely with the general version. | 133 | * nicely with the general version. |
| @@ -194,8 +198,20 @@ void Config::ReadPlayerValue(std::size_t player_index) { | |||
| 194 | }(); | 198 | }(); |
| 195 | 199 | ||
| 196 | auto& player = Settings::values.players.GetValue()[player_index]; | 200 | auto& player = Settings::values.players.GetValue()[player_index]; |
| 201 | if (IsCustomConfig()) { | ||
| 202 | const auto profile_name = | ||
| 203 | qt_config->value(QStringLiteral("%1profile_name").arg(player_prefix), QString{}) | ||
| 204 | .toString() | ||
| 205 | .toStdString(); | ||
| 206 | if (profile_name.empty()) { | ||
| 207 | // Use the global input config | ||
| 208 | player = Settings::values.players.GetValue(true)[player_index]; | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | player.profile_name = profile_name; | ||
| 212 | } | ||
| 197 | 213 | ||
| 198 | if (player_prefix.isEmpty()) { | 214 | if (player_prefix.isEmpty() && Settings::IsConfiguringGlobal()) { |
| 199 | const auto controller = static_cast<Settings::ControllerType>( | 215 | const auto controller = static_cast<Settings::ControllerType>( |
| 200 | qt_config | 216 | qt_config |
| 201 | ->value(QStringLiteral("%1type").arg(player_prefix), | 217 | ->value(QStringLiteral("%1type").arg(player_prefix), |
| @@ -388,9 +404,26 @@ void Config::ReadAudioValues() { | |||
| 388 | void Config::ReadControlValues() { | 404 | void Config::ReadControlValues() { |
| 389 | qt_config->beginGroup(QStringLiteral("Controls")); | 405 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 390 | 406 | ||
| 407 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 391 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 408 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 392 | ReadPlayerValue(p); | 409 | ReadPlayerValue(p); |
| 393 | } | 410 | } |
| 411 | ReadGlobalSetting(Settings::values.use_docked_mode); | ||
| 412 | |||
| 413 | // Disable docked mode if handheld is selected | ||
| 414 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | ||
| 415 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 416 | Settings::values.use_docked_mode.SetGlobal(!IsCustomConfig()); | ||
| 417 | Settings::values.use_docked_mode.SetValue(false); | ||
| 418 | } | ||
| 419 | |||
| 420 | ReadGlobalSetting(Settings::values.vibration_enabled); | ||
| 421 | ReadGlobalSetting(Settings::values.enable_accurate_vibrations); | ||
| 422 | ReadGlobalSetting(Settings::values.motion_enabled); | ||
| 423 | if (IsCustomConfig()) { | ||
| 424 | qt_config->endGroup(); | ||
| 425 | return; | ||
| 426 | } | ||
| 394 | ReadDebugValues(); | 427 | ReadDebugValues(); |
| 395 | ReadKeyboardValues(); | 428 | ReadKeyboardValues(); |
| 396 | ReadMouseValues(); | 429 | ReadMouseValues(); |
| @@ -412,18 +445,6 @@ void Config::ReadControlValues() { | |||
| 412 | ReadBasicSetting(Settings::values.tas_loop); | 445 | ReadBasicSetting(Settings::values.tas_loop); |
| 413 | ReadBasicSetting(Settings::values.pause_tas_on_load); | 446 | ReadBasicSetting(Settings::values.pause_tas_on_load); |
| 414 | 447 | ||
| 415 | ReadGlobalSetting(Settings::values.use_docked_mode); | ||
| 416 | |||
| 417 | // Disable docked mode if handheld is selected | ||
| 418 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | ||
| 419 | if (controller_type == Settings::ControllerType::Handheld) { | ||
| 420 | Settings::values.use_docked_mode.SetValue(false); | ||
| 421 | } | ||
| 422 | |||
| 423 | ReadGlobalSetting(Settings::values.vibration_enabled); | ||
| 424 | ReadGlobalSetting(Settings::values.enable_accurate_vibrations); | ||
| 425 | ReadGlobalSetting(Settings::values.motion_enabled); | ||
| 426 | |||
| 427 | ReadBasicSetting(Settings::values.controller_navigation); | 448 | ReadBasicSetting(Settings::values.controller_navigation); |
| 428 | 449 | ||
| 429 | qt_config->endGroup(); | 450 | qt_config->endGroup(); |
| @@ -658,6 +679,7 @@ void Config::ReadCpuValues() { | |||
| 658 | ReadBasicSetting(Settings::values.cpuopt_fastmem); | 679 | ReadBasicSetting(Settings::values.cpuopt_fastmem); |
| 659 | ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives); | 680 | ReadBasicSetting(Settings::values.cpuopt_fastmem_exclusives); |
| 660 | ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives); | 681 | ReadBasicSetting(Settings::values.cpuopt_recompile_exclusives); |
| 682 | ReadBasicSetting(Settings::values.cpuopt_ignore_memory_aborts); | ||
| 661 | } | 683 | } |
| 662 | 684 | ||
| 663 | qt_config->endGroup(); | 685 | qt_config->endGroup(); |
| @@ -905,7 +927,6 @@ void Config::ReadMultiplayerValues() { | |||
| 905 | 927 | ||
| 906 | void Config::ReadValues() { | 928 | void Config::ReadValues() { |
| 907 | if (global) { | 929 | if (global) { |
| 908 | ReadControlValues(); | ||
| 909 | ReadDataStorageValues(); | 930 | ReadDataStorageValues(); |
| 910 | ReadDebuggingValues(); | 931 | ReadDebuggingValues(); |
| 911 | ReadDisabledAddOnValues(); | 932 | ReadDisabledAddOnValues(); |
| @@ -914,6 +935,7 @@ void Config::ReadValues() { | |||
| 914 | ReadWebServiceValues(); | 935 | ReadWebServiceValues(); |
| 915 | ReadMiscellaneousValues(); | 936 | ReadMiscellaneousValues(); |
| 916 | } | 937 | } |
| 938 | ReadControlValues(); | ||
| 917 | ReadCoreValues(); | 939 | ReadCoreValues(); |
| 918 | ReadCpuValues(); | 940 | ReadCpuValues(); |
| 919 | ReadRendererValues(); | 941 | ReadRendererValues(); |
| @@ -932,12 +954,20 @@ void Config::SavePlayerValue(std::size_t player_index) { | |||
| 932 | }(); | 954 | }(); |
| 933 | 955 | ||
| 934 | const auto& player = Settings::values.players.GetValue()[player_index]; | 956 | const auto& player = Settings::values.players.GetValue()[player_index]; |
| 957 | if (IsCustomConfig()) { | ||
| 958 | if (player.profile_name.empty()) { | ||
| 959 | // No custom profile selected | ||
| 960 | return; | ||
| 961 | } | ||
| 962 | WriteSetting(QStringLiteral("%1profile_name").arg(player_prefix), | ||
| 963 | QString::fromStdString(player.profile_name), QString{}); | ||
| 964 | } | ||
| 935 | 965 | ||
| 936 | WriteSetting(QStringLiteral("%1type").arg(player_prefix), | 966 | WriteSetting(QStringLiteral("%1type").arg(player_prefix), |
| 937 | static_cast<u8>(player.controller_type), | 967 | static_cast<u8>(player.controller_type), |
| 938 | static_cast<u8>(Settings::ControllerType::ProController)); | 968 | static_cast<u8>(Settings::ControllerType::ProController)); |
| 939 | 969 | ||
| 940 | if (!player_prefix.isEmpty()) { | 970 | if (!player_prefix.isEmpty() || !Settings::IsConfiguringGlobal()) { |
| 941 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, | 971 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, |
| 942 | player_index == 0); | 972 | player_index == 0); |
| 943 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), | 973 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), |
| @@ -1055,7 +1085,6 @@ void Config::SaveIrCameraValues() { | |||
| 1055 | 1085 | ||
| 1056 | void Config::SaveValues() { | 1086 | void Config::SaveValues() { |
| 1057 | if (global) { | 1087 | if (global) { |
| 1058 | SaveControlValues(); | ||
| 1059 | SaveDataStorageValues(); | 1088 | SaveDataStorageValues(); |
| 1060 | SaveDebuggingValues(); | 1089 | SaveDebuggingValues(); |
| 1061 | SaveDisabledAddOnValues(); | 1090 | SaveDisabledAddOnValues(); |
| @@ -1064,6 +1093,7 @@ void Config::SaveValues() { | |||
| 1064 | SaveWebServiceValues(); | 1093 | SaveWebServiceValues(); |
| 1065 | SaveMiscellaneousValues(); | 1094 | SaveMiscellaneousValues(); |
| 1066 | } | 1095 | } |
| 1096 | SaveControlValues(); | ||
| 1067 | SaveCoreValues(); | 1097 | SaveCoreValues(); |
| 1068 | SaveCpuValues(); | 1098 | SaveCpuValues(); |
| 1069 | SaveRendererValues(); | 1099 | SaveRendererValues(); |
| @@ -1088,9 +1118,14 @@ void Config::SaveAudioValues() { | |||
| 1088 | void Config::SaveControlValues() { | 1118 | void Config::SaveControlValues() { |
| 1089 | qt_config->beginGroup(QStringLiteral("Controls")); | 1119 | qt_config->beginGroup(QStringLiteral("Controls")); |
| 1090 | 1120 | ||
| 1121 | Settings::values.players.SetGlobal(!IsCustomConfig()); | ||
| 1091 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 1122 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| 1092 | SavePlayerValue(p); | 1123 | SavePlayerValue(p); |
| 1093 | } | 1124 | } |
| 1125 | if (IsCustomConfig()) { | ||
| 1126 | qt_config->endGroup(); | ||
| 1127 | return; | ||
| 1128 | } | ||
| 1094 | SaveDebugValues(); | 1129 | SaveDebugValues(); |
| 1095 | SaveMouseValues(); | 1130 | SaveMouseValues(); |
| 1096 | SaveTouchscreenValues(); | 1131 | SaveTouchscreenValues(); |
| @@ -1257,6 +1292,7 @@ void Config::SaveCpuValues() { | |||
| 1257 | WriteBasicSetting(Settings::values.cpuopt_fastmem); | 1292 | WriteBasicSetting(Settings::values.cpuopt_fastmem); |
| 1258 | WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives); | 1293 | WriteBasicSetting(Settings::values.cpuopt_fastmem_exclusives); |
| 1259 | WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives); | 1294 | WriteBasicSetting(Settings::values.cpuopt_recompile_exclusives); |
| 1295 | WriteBasicSetting(Settings::values.cpuopt_ignore_memory_aborts); | ||
| 1260 | } | 1296 | } |
| 1261 | 1297 | ||
| 1262 | qt_config->endGroup(); | 1298 | qt_config->endGroup(); |
| @@ -1579,6 +1615,13 @@ void Config::SaveControlPlayerValue(std::size_t player_index) { | |||
| 1579 | qt_config->endGroup(); | 1615 | qt_config->endGroup(); |
| 1580 | } | 1616 | } |
| 1581 | 1617 | ||
| 1618 | void Config::ClearControlPlayerValues() { | ||
| 1619 | qt_config->beginGroup(QStringLiteral("Controls")); | ||
| 1620 | // If key is an empty string, all keys in the current group() are removed. | ||
| 1621 | qt_config->remove(QString{}); | ||
| 1622 | qt_config->endGroup(); | ||
| 1623 | } | ||
| 1624 | |||
| 1582 | const std::string& Config::GetConfigFilePath() const { | 1625 | const std::string& Config::GetConfigFilePath() const { |
| 1583 | return qt_config_loc; | 1626 | return qt_config_loc; |
| 1584 | } | 1627 | } |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 06fa7d2d0..7d26e9ab6 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -34,6 +34,7 @@ public: | |||
| 34 | 34 | ||
| 35 | void ReadControlPlayerValue(std::size_t player_index); | 35 | void ReadControlPlayerValue(std::size_t player_index); |
| 36 | void SaveControlPlayerValue(std::size_t player_index); | 36 | void SaveControlPlayerValue(std::size_t player_index); |
| 37 | void ClearControlPlayerValues(); | ||
| 37 | 38 | ||
| 38 | const std::string& GetConfigFilePath() const; | 39 | const std::string& GetConfigFilePath() const; |
| 39 | 40 | ||
| @@ -58,6 +59,7 @@ public: | |||
| 58 | 59 | ||
| 59 | private: | 60 | private: |
| 60 | void Initialize(const std::string& config_name); | 61 | void Initialize(const std::string& config_name); |
| 62 | bool IsCustomConfig(); | ||
| 61 | 63 | ||
| 62 | void ReadValues(); | 64 | void ReadValues(); |
| 63 | void ReadPlayerValue(std::size_t player_index); | 65 | void ReadPlayerValue(std::size_t player_index); |
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp index 3c302ec16..8cfef0cc1 100644 --- a/src/yuzu/configuration/configure_cpu_debug.cpp +++ b/src/yuzu/configuration/configure_cpu_debug.cpp | |||
| @@ -45,6 +45,9 @@ void ConfigureCpuDebug::SetConfiguration() { | |||
| 45 | ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock); | 45 | ui->cpuopt_recompile_exclusives->setEnabled(runtime_lock); |
| 46 | ui->cpuopt_recompile_exclusives->setChecked( | 46 | ui->cpuopt_recompile_exclusives->setChecked( |
| 47 | Settings::values.cpuopt_recompile_exclusives.GetValue()); | 47 | Settings::values.cpuopt_recompile_exclusives.GetValue()); |
| 48 | ui->cpuopt_ignore_memory_aborts->setEnabled(runtime_lock); | ||
| 49 | ui->cpuopt_ignore_memory_aborts->setChecked( | ||
| 50 | Settings::values.cpuopt_ignore_memory_aborts.GetValue()); | ||
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | void ConfigureCpuDebug::ApplyConfiguration() { | 53 | void ConfigureCpuDebug::ApplyConfiguration() { |
| @@ -59,6 +62,7 @@ void ConfigureCpuDebug::ApplyConfiguration() { | |||
| 59 | Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked(); | 62 | Settings::values.cpuopt_fastmem = ui->cpuopt_fastmem->isChecked(); |
| 60 | Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked(); | 63 | Settings::values.cpuopt_fastmem_exclusives = ui->cpuopt_fastmem_exclusives->isChecked(); |
| 61 | Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked(); | 64 | Settings::values.cpuopt_recompile_exclusives = ui->cpuopt_recompile_exclusives->isChecked(); |
| 65 | Settings::values.cpuopt_ignore_memory_aborts = ui->cpuopt_ignore_memory_aborts->isChecked(); | ||
| 62 | } | 66 | } |
| 63 | 67 | ||
| 64 | void ConfigureCpuDebug::changeEvent(QEvent* event) { | 68 | void ConfigureCpuDebug::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/configuration/configure_cpu_debug.ui b/src/yuzu/configuration/configure_cpu_debug.ui index 2bc268810..3010f7fad 100644 --- a/src/yuzu/configuration/configure_cpu_debug.ui +++ b/src/yuzu/configuration/configure_cpu_debug.ui | |||
| @@ -175,6 +175,19 @@ | |||
| 175 | </property> | 175 | </property> |
| 176 | </widget> | 176 | </widget> |
| 177 | </item> | 177 | </item> |
| 178 | <item> | ||
| 179 | <widget class="QCheckBox" name="cpuopt_ignore_memory_aborts"> | ||
| 180 | <property name="toolTip"> | ||
| 181 | <string> | ||
| 182 | <div style="white-space: nowrap">This optimization speeds up memory accesses by allowing invalid memory accesses to succeed.</div> | ||
| 183 | <div style="white-space: nowrap">Enabling it reduces the overhead of all memory accesses and has no impact on programs that don't access invalid memory.</div> | ||
| 184 | </string> | ||
| 185 | </property> | ||
| 186 | <property name="text"> | ||
| 187 | <string>Enable fallbacks for invalid memory accesses</string> | ||
| 188 | </property> | ||
| 189 | </widget> | ||
| 190 | </item> | ||
| 178 | </layout> | 191 | </layout> |
| 179 | </widget> | 192 | </widget> |
| 180 | </item> | 193 | </item> |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index f1385e972..e9388daad 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -31,7 +31,7 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren | |||
| 31 | 31 | ||
| 32 | ui->backend->addItem(QStringLiteral("GLSL")); | 32 | ui->backend->addItem(QStringLiteral("GLSL")); |
| 33 | ui->backend->addItem(tr("GLASM (Assembly Shaders, NVIDIA Only)")); | 33 | ui->backend->addItem(tr("GLASM (Assembly Shaders, NVIDIA Only)")); |
| 34 | ui->backend->addItem(QStringLiteral("SPIR-V (Experimental, Mesa Only)")); | 34 | ui->backend->addItem(tr("SPIR-V (Experimental, Mesa Only)")); |
| 35 | 35 | ||
| 36 | SetupPerGameUI(); | 36 | SetupPerGameUI(); |
| 37 | 37 | ||
| @@ -260,6 +260,7 @@ void ConfigureGraphics::ApplyConfiguration() { | |||
| 260 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); | 260 | Settings::values.renderer_backend.SetValue(GetCurrentGraphicsBackend()); |
| 261 | switch (GetCurrentGraphicsBackend()) { | 261 | switch (GetCurrentGraphicsBackend()) { |
| 262 | case Settings::RendererBackend::OpenGL: | 262 | case Settings::RendererBackend::OpenGL: |
| 263 | case Settings::RendererBackend::Null: | ||
| 263 | Settings::values.shader_backend.SetGlobal(false); | 264 | Settings::values.shader_backend.SetGlobal(false); |
| 264 | Settings::values.vulkan_device.SetGlobal(true); | 265 | Settings::values.vulkan_device.SetGlobal(true); |
| 265 | Settings::values.shader_backend.SetValue(shader_backend); | 266 | Settings::values.shader_backend.SetValue(shader_backend); |
| @@ -348,6 +349,10 @@ void ConfigureGraphics::UpdateAPILayout() { | |||
| 348 | ui->device_widget->setVisible(true); | 349 | ui->device_widget->setVisible(true); |
| 349 | ui->backend_widget->setVisible(false); | 350 | ui->backend_widget->setVisible(false); |
| 350 | break; | 351 | break; |
| 352 | case Settings::RendererBackend::Null: | ||
| 353 | ui->device_widget->setVisible(false); | ||
| 354 | ui->backend_widget->setVisible(false); | ||
| 355 | break; | ||
| 351 | } | 356 | } |
| 352 | } | 357 | } |
| 353 | 358 | ||
| @@ -360,7 +365,7 @@ void ConfigureGraphics::RetrieveVulkanDevices() try { | |||
| 360 | 365 | ||
| 361 | vk::InstanceDispatch dld; | 366 | vk::InstanceDispatch dld; |
| 362 | const Common::DynamicLibrary library = OpenLibrary(); | 367 | const Common::DynamicLibrary library = OpenLibrary(); |
| 363 | const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0); | 368 | const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1); |
| 364 | const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices(); | 369 | const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices(); |
| 365 | 370 | ||
| 366 | vulkan_devices.clear(); | 371 | vulkan_devices.clear(); |
diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 37271f956..f78396690 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui | |||
| @@ -139,6 +139,11 @@ | |||
| 139 | <string notr="true">Vulkan</string> | 139 | <string notr="true">Vulkan</string> |
| 140 | </property> | 140 | </property> |
| 141 | </item> | 141 | </item> |
| 142 | <item> | ||
| 143 | <property name="text"> | ||
| 144 | <string>None</string> | ||
| 145 | </property> | ||
| 146 | </item> | ||
| 142 | </widget> | 147 | </widget> |
| 143 | </item> | 148 | </item> |
| 144 | </layout> | 149 | </layout> |
diff --git a/src/yuzu/configuration/configure_input_per_game.cpp b/src/yuzu/configuration/configure_input_per_game.cpp new file mode 100644 index 000000000..78e65d468 --- /dev/null +++ b/src/yuzu/configuration/configure_input_per_game.cpp | |||
| @@ -0,0 +1,115 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/settings.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hid/emulated_controller.h" | ||
| 7 | #include "core/hid/hid_core.h" | ||
| 8 | #include "ui_configure_input_per_game.h" | ||
| 9 | #include "yuzu/configuration/config.h" | ||
| 10 | #include "yuzu/configuration/configure_input_per_game.h" | ||
| 11 | #include "yuzu/configuration/input_profiles.h" | ||
| 12 | |||
| 13 | ConfigureInputPerGame::ConfigureInputPerGame(Core::System& system_, Config* config_, | ||
| 14 | QWidget* parent) | ||
| 15 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureInputPerGame>()), | ||
| 16 | profiles(std::make_unique<InputProfiles>()), system{system_}, config{config_} { | ||
| 17 | ui->setupUi(this); | ||
| 18 | const std::array labels = { | ||
| 19 | ui->label_player_1, ui->label_player_2, ui->label_player_3, ui->label_player_4, | ||
| 20 | ui->label_player_5, ui->label_player_6, ui->label_player_7, ui->label_player_8, | ||
| 21 | }; | ||
| 22 | profile_comboboxes = { | ||
| 23 | ui->profile_player_1, ui->profile_player_2, ui->profile_player_3, ui->profile_player_4, | ||
| 24 | ui->profile_player_5, ui->profile_player_6, ui->profile_player_7, ui->profile_player_8, | ||
| 25 | }; | ||
| 26 | |||
| 27 | Settings::values.players.SetGlobal(false); | ||
| 28 | |||
| 29 | const auto& profile_names = profiles->GetInputProfileNames(); | ||
| 30 | const auto populate_profiles = [this, &profile_names](size_t player_index) { | ||
| 31 | const auto previous_profile = | ||
| 32 | Settings::values.players.GetValue()[player_index].profile_name; | ||
| 33 | |||
| 34 | auto* const player_combobox = profile_comboboxes[player_index]; | ||
| 35 | player_combobox->addItem(tr("Use global input configuration")); | ||
| 36 | |||
| 37 | for (size_t index = 0; index < profile_names.size(); ++index) { | ||
| 38 | const auto& profile_name = profile_names[index]; | ||
| 39 | player_combobox->addItem(QString::fromStdString(profile_name)); | ||
| 40 | if (profile_name == previous_profile) { | ||
| 41 | // offset by 1 since the first element is the global config | ||
| 42 | player_combobox->setCurrentIndex(static_cast<int>(index + 1)); | ||
| 43 | } | ||
| 44 | } | ||
| 45 | }; | ||
| 46 | for (size_t index = 0; index < profile_comboboxes.size(); ++index) { | ||
| 47 | labels[index]->setText(tr("Player %1 profile").arg(index + 1)); | ||
| 48 | populate_profiles(index); | ||
| 49 | } | ||
| 50 | |||
| 51 | LoadConfiguration(); | ||
| 52 | } | ||
| 53 | |||
| 54 | void ConfigureInputPerGame::ApplyConfiguration() { | ||
| 55 | LoadConfiguration(); | ||
| 56 | SaveConfiguration(); | ||
| 57 | } | ||
| 58 | |||
| 59 | void ConfigureInputPerGame::LoadConfiguration() { | ||
| 60 | static constexpr size_t HANDHELD_INDEX = 8; | ||
| 61 | |||
| 62 | auto& hid_core = system.HIDCore(); | ||
| 63 | for (size_t player_index = 0; player_index < profile_comboboxes.size(); ++player_index) { | ||
| 64 | Settings::values.players.SetGlobal(false); | ||
| 65 | |||
| 66 | auto* emulated_controller = hid_core.GetEmulatedControllerByIndex(player_index); | ||
| 67 | auto* const player_combobox = profile_comboboxes[player_index]; | ||
| 68 | |||
| 69 | const auto selection_index = player_combobox->currentIndex(); | ||
| 70 | if (selection_index == 0) { | ||
| 71 | Settings::values.players.GetValue()[player_index].profile_name = ""; | ||
| 72 | if (player_index == 0) { | ||
| 73 | Settings::values.players.GetValue()[HANDHELD_INDEX] = {}; | ||
| 74 | } | ||
| 75 | Settings::values.players.SetGlobal(true); | ||
| 76 | emulated_controller->ReloadFromSettings(); | ||
| 77 | continue; | ||
| 78 | } | ||
| 79 | const auto profile_name = player_combobox->itemText(selection_index).toStdString(); | ||
| 80 | if (profile_name.empty()) { | ||
| 81 | continue; | ||
| 82 | } | ||
| 83 | auto& player = Settings::values.players.GetValue()[player_index]; | ||
| 84 | player.profile_name = profile_name; | ||
| 85 | // Read from the profile into the custom player settings | ||
| 86 | profiles->LoadProfile(profile_name, player_index); | ||
| 87 | // Make sure the controller is connected | ||
| 88 | player.connected = true; | ||
| 89 | |||
| 90 | emulated_controller->ReloadFromSettings(); | ||
| 91 | |||
| 92 | if (player_index > 0) { | ||
| 93 | continue; | ||
| 94 | } | ||
| 95 | // Handle Handheld cases | ||
| 96 | auto& handheld_player = Settings::values.players.GetValue()[HANDHELD_INDEX]; | ||
| 97 | auto* handheld_controller = hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld); | ||
| 98 | if (player.controller_type == Settings::ControllerType::Handheld) { | ||
| 99 | handheld_player = player; | ||
| 100 | } else { | ||
| 101 | handheld_player = {}; | ||
| 102 | } | ||
| 103 | handheld_controller->ReloadFromSettings(); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | void ConfigureInputPerGame::SaveConfiguration() { | ||
| 108 | Settings::values.players.SetGlobal(false); | ||
| 109 | |||
| 110 | // Clear all controls from the config in case the user reverted back to globals | ||
| 111 | config->ClearControlPlayerValues(); | ||
| 112 | for (size_t index = 0; index < Settings::values.players.GetValue().size(); ++index) { | ||
| 113 | config->SaveControlPlayerValue(index); | ||
| 114 | } | ||
| 115 | } | ||
diff --git a/src/yuzu/configuration/configure_input_per_game.h b/src/yuzu/configuration/configure_input_per_game.h new file mode 100644 index 000000000..660faf574 --- /dev/null +++ b/src/yuzu/configuration/configure_input_per_game.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include <QWidget> | ||
| 9 | |||
| 10 | #include "ui_configure_input_per_game.h" | ||
| 11 | #include "yuzu/configuration/input_profiles.h" | ||
| 12 | |||
| 13 | class QComboBox; | ||
| 14 | |||
| 15 | namespace Core { | ||
| 16 | class System; | ||
| 17 | } // namespace Core | ||
| 18 | |||
| 19 | class Config; | ||
| 20 | |||
| 21 | class ConfigureInputPerGame : public QWidget { | ||
| 22 | Q_OBJECT | ||
| 23 | |||
| 24 | public: | ||
| 25 | explicit ConfigureInputPerGame(Core::System& system_, Config* config_, | ||
| 26 | QWidget* parent = nullptr); | ||
| 27 | |||
| 28 | /// Load and Save configurations to settings file. | ||
| 29 | void ApplyConfiguration(); | ||
| 30 | |||
| 31 | private: | ||
| 32 | /// Load configuration from settings file. | ||
| 33 | void LoadConfiguration(); | ||
| 34 | |||
| 35 | /// Save configuration to settings file. | ||
| 36 | void SaveConfiguration(); | ||
| 37 | |||
| 38 | std::unique_ptr<Ui::ConfigureInputPerGame> ui; | ||
| 39 | std::unique_ptr<InputProfiles> profiles; | ||
| 40 | |||
| 41 | std::array<QComboBox*, 8> profile_comboboxes; | ||
| 42 | |||
| 43 | Core::System& system; | ||
| 44 | Config* config; | ||
| 45 | }; | ||
diff --git a/src/yuzu/configuration/configure_input_per_game.ui b/src/yuzu/configuration/configure_input_per_game.ui new file mode 100644 index 000000000..fbd8eab1c --- /dev/null +++ b/src/yuzu/configuration/configure_input_per_game.ui | |||
| @@ -0,0 +1,333 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureInputPerGame</class> | ||
| 4 | <widget class="QWidget" name="PerGameInput"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>541</width> | ||
| 10 | <height>759</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Form</string> | ||
| 15 | </property> | ||
| 16 | <property name="accessibleName"> | ||
| 17 | <string>Graphics</string> | ||
| 18 | </property> | ||
| 19 | <layout class="QVBoxLayout" name="verticalLayout_1"> | ||
| 20 | <item> | ||
| 21 | <layout class="QVBoxLayout" name="verticalLayout_2"> | ||
| 22 | <property name="spacing"> | ||
| 23 | <number>0</number> | ||
| 24 | </property> | ||
| 25 | <item> | ||
| 26 | <widget class="QGroupBox" name="groupBox"> | ||
| 27 | <property name="title"> | ||
| 28 | <string>Input Profiles</string> | ||
| 29 | </property> | ||
| 30 | <layout class="QVBoxLayout" name="verticalLayout_4"> | ||
| 31 | <item> | ||
| 32 | <widget class="QWidget" name="player_1" native="true"> | ||
| 33 | <layout class="QHBoxLayout" name="input_profile_layout_1"> | ||
| 34 | <property name="leftMargin"> | ||
| 35 | <number>0</number> | ||
| 36 | </property> | ||
| 37 | <property name="topMargin"> | ||
| 38 | <number>0</number> | ||
| 39 | </property> | ||
| 40 | <property name="rightMargin"> | ||
| 41 | <number>0</number> | ||
| 42 | </property> | ||
| 43 | <property name="bottomMargin"> | ||
| 44 | <number>0</number> | ||
| 45 | </property> | ||
| 46 | <item> | ||
| 47 | <widget class="QLabel" name="label_player_1"> | ||
| 48 | <property name="text"> | ||
| 49 | <string>Player 1 Profile</string> | ||
| 50 | </property> | ||
| 51 | </widget> | ||
| 52 | </item> | ||
| 53 | <item> | ||
| 54 | <widget class="QComboBox" name="profile_player_1"> | ||
| 55 | <property name="sizePolicy"> | ||
| 56 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 57 | <horstretch>0</horstretch> | ||
| 58 | <verstretch>0</verstretch> | ||
| 59 | </sizepolicy> | ||
| 60 | </property> | ||
| 61 | </widget> | ||
| 62 | </item> | ||
| 63 | </layout> | ||
| 64 | </widget> | ||
| 65 | </item> | ||
| 66 | <item> | ||
| 67 | <widget class="QWidget" name="player_2" native="true"> | ||
| 68 | <layout class="QHBoxLayout" name="input_profile_layout_2"> | ||
| 69 | <property name="leftMargin"> | ||
| 70 | <number>0</number> | ||
| 71 | </property> | ||
| 72 | <property name="topMargin"> | ||
| 73 | <number>0</number> | ||
| 74 | </property> | ||
| 75 | <property name="rightMargin"> | ||
| 76 | <number>0</number> | ||
| 77 | </property> | ||
| 78 | <property name="bottomMargin"> | ||
| 79 | <number>0</number> | ||
| 80 | </property> | ||
| 81 | <item> | ||
| 82 | <widget class="QLabel" name="label_player_2"> | ||
| 83 | <property name="text"> | ||
| 84 | <string>Player 2 Profile</string> | ||
| 85 | </property> | ||
| 86 | </widget> | ||
| 87 | </item> | ||
| 88 | <item> | ||
| 89 | <widget class="QComboBox" name="profile_player_2"> | ||
| 90 | <property name="sizePolicy"> | ||
| 91 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 92 | <horstretch>0</horstretch> | ||
| 93 | <verstretch>0</verstretch> | ||
| 94 | </sizepolicy> | ||
| 95 | </property> | ||
| 96 | </widget> | ||
| 97 | </item> | ||
| 98 | </layout> | ||
| 99 | </widget> | ||
| 100 | </item> | ||
| 101 | <item> | ||
| 102 | <widget class="QWidget" name="player_3" native="true"> | ||
| 103 | <layout class="QHBoxLayout" name="input_profile_layout_3"> | ||
| 104 | <property name="leftMargin"> | ||
| 105 | <number>0</number> | ||
| 106 | </property> | ||
| 107 | <property name="topMargin"> | ||
| 108 | <number>0</number> | ||
| 109 | </property> | ||
| 110 | <property name="rightMargin"> | ||
| 111 | <number>0</number> | ||
| 112 | </property> | ||
| 113 | <property name="bottomMargin"> | ||
| 114 | <number>0</number> | ||
| 115 | </property> | ||
| 116 | <item> | ||
| 117 | <widget class="QLabel" name="label_player_3"> | ||
| 118 | <property name="text"> | ||
| 119 | <string>Player 3 Profile</string> | ||
| 120 | </property> | ||
| 121 | </widget> | ||
| 122 | </item> | ||
| 123 | <item> | ||
| 124 | <widget class="QComboBox" name="profile_player_3"> | ||
| 125 | <property name="sizePolicy"> | ||
| 126 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 127 | <horstretch>0</horstretch> | ||
| 128 | <verstretch>0</verstretch> | ||
| 129 | </sizepolicy> | ||
| 130 | </property> | ||
| 131 | </widget> | ||
| 132 | </item> | ||
| 133 | </layout> | ||
| 134 | </widget> | ||
| 135 | </item> | ||
| 136 | <item> | ||
| 137 | <widget class="QWidget" name="player_4" native="true"> | ||
| 138 | <layout class="QHBoxLayout" name="input_profile_layout_4"> | ||
| 139 | <property name="leftMargin"> | ||
| 140 | <number>0</number> | ||
| 141 | </property> | ||
| 142 | <property name="topMargin"> | ||
| 143 | <number>0</number> | ||
| 144 | </property> | ||
| 145 | <property name="rightMargin"> | ||
| 146 | <number>0</number> | ||
| 147 | </property> | ||
| 148 | <property name="bottomMargin"> | ||
| 149 | <number>0</number> | ||
| 150 | </property> | ||
| 151 | <item> | ||
| 152 | <widget class="QLabel" name="label_player_4"> | ||
| 153 | <property name="text"> | ||
| 154 | <string>Player 4 Profile</string> | ||
| 155 | </property> | ||
| 156 | </widget> | ||
| 157 | </item> | ||
| 158 | <item> | ||
| 159 | <widget class="QComboBox" name="profile_player_4"> | ||
| 160 | <property name="sizePolicy"> | ||
| 161 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 162 | <horstretch>0</horstretch> | ||
| 163 | <verstretch>0</verstretch> | ||
| 164 | </sizepolicy> | ||
| 165 | </property> | ||
| 166 | </widget> | ||
| 167 | </item> | ||
| 168 | </layout> | ||
| 169 | </widget> | ||
| 170 | </item> | ||
| 171 | <item> | ||
| 172 | <widget class="QWidget" name="player_5" native="true"> | ||
| 173 | <layout class="QHBoxLayout" name="input_profile_layout_5"> | ||
| 174 | <property name="leftMargin"> | ||
| 175 | <number>0</number> | ||
| 176 | </property> | ||
| 177 | <property name="topMargin"> | ||
| 178 | <number>0</number> | ||
| 179 | </property> | ||
| 180 | <property name="rightMargin"> | ||
| 181 | <number>0</number> | ||
| 182 | </property> | ||
| 183 | <property name="bottomMargin"> | ||
| 184 | <number>0</number> | ||
| 185 | </property> | ||
| 186 | <item> | ||
| 187 | <widget class="QLabel" name="label_player_5"> | ||
| 188 | <property name="text"> | ||
| 189 | <string>Player 5 Profile</string> | ||
| 190 | </property> | ||
| 191 | </widget> | ||
| 192 | </item> | ||
| 193 | <item> | ||
| 194 | <widget class="QComboBox" name="profile_player_5"> | ||
| 195 | <property name="sizePolicy"> | ||
| 196 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 197 | <horstretch>0</horstretch> | ||
| 198 | <verstretch>0</verstretch> | ||
| 199 | </sizepolicy> | ||
| 200 | </property> | ||
| 201 | </widget> | ||
| 202 | </item> | ||
| 203 | </layout> | ||
| 204 | </widget> | ||
| 205 | </item> | ||
| 206 | <item> | ||
| 207 | <widget class="QWidget" name="player_6" native="true"> | ||
| 208 | <layout class="QHBoxLayout" name="input_profile_layout_6"> | ||
| 209 | <property name="leftMargin"> | ||
| 210 | <number>0</number> | ||
| 211 | </property> | ||
| 212 | <property name="topMargin"> | ||
| 213 | <number>0</number> | ||
| 214 | </property> | ||
| 215 | <property name="rightMargin"> | ||
| 216 | <number>0</number> | ||
| 217 | </property> | ||
| 218 | <property name="bottomMargin"> | ||
| 219 | <number>0</number> | ||
| 220 | </property> | ||
| 221 | <item> | ||
| 222 | <widget class="QLabel" name="label_player_6"> | ||
| 223 | <property name="text"> | ||
| 224 | <string>Player 6 Profile</string> | ||
| 225 | </property> | ||
| 226 | </widget> | ||
| 227 | </item> | ||
| 228 | <item> | ||
| 229 | <widget class="QComboBox" name="profile_player_6"> | ||
| 230 | <property name="sizePolicy"> | ||
| 231 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 232 | <horstretch>0</horstretch> | ||
| 233 | <verstretch>0</verstretch> | ||
| 234 | </sizepolicy> | ||
| 235 | </property> | ||
| 236 | </widget> | ||
| 237 | </item> | ||
| 238 | </layout> | ||
| 239 | </widget> | ||
| 240 | </item> | ||
| 241 | <item> | ||
| 242 | <widget class="QWidget" name="player_7" native="true"> | ||
| 243 | <layout class="QHBoxLayout" name="input_profile_layout_7"> | ||
| 244 | <property name="leftMargin"> | ||
| 245 | <number>0</number> | ||
| 246 | </property> | ||
| 247 | <property name="topMargin"> | ||
| 248 | <number>0</number> | ||
| 249 | </property> | ||
| 250 | <property name="rightMargin"> | ||
| 251 | <number>0</number> | ||
| 252 | </property> | ||
| 253 | <property name="bottomMargin"> | ||
| 254 | <number>0</number> | ||
| 255 | </property> | ||
| 256 | <item> | ||
| 257 | <widget class="QLabel" name="label_player_7"> | ||
| 258 | <property name="text"> | ||
| 259 | <string>Player 7 Profile</string> | ||
| 260 | </property> | ||
| 261 | </widget> | ||
| 262 | </item> | ||
| 263 | <item> | ||
| 264 | <widget class="QComboBox" name="profile_player_7"> | ||
| 265 | <property name="sizePolicy"> | ||
| 266 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 267 | <horstretch>0</horstretch> | ||
| 268 | <verstretch>0</verstretch> | ||
| 269 | </sizepolicy> | ||
| 270 | </property> | ||
| 271 | </widget> | ||
| 272 | </item> | ||
| 273 | </layout> | ||
| 274 | </widget> | ||
| 275 | </item> | ||
| 276 | <item> | ||
| 277 | <widget class="QWidget" name="player_8" native="true"> | ||
| 278 | <layout class="QHBoxLayout" name="input_profile_layout_8"> | ||
| 279 | <property name="leftMargin"> | ||
| 280 | <number>0</number> | ||
| 281 | </property> | ||
| 282 | <property name="topMargin"> | ||
| 283 | <number>0</number> | ||
| 284 | </property> | ||
| 285 | <property name="rightMargin"> | ||
| 286 | <number>0</number> | ||
| 287 | </property> | ||
| 288 | <property name="bottomMargin"> | ||
| 289 | <number>0</number> | ||
| 290 | </property> | ||
| 291 | <item> | ||
| 292 | <widget class="QLabel" name="label_player_8"> | ||
| 293 | <property name="text"> | ||
| 294 | <string>Player 8 Profile</string> | ||
| 295 | </property> | ||
| 296 | </widget> | ||
| 297 | </item> | ||
| 298 | <item> | ||
| 299 | <widget class="QComboBox" name="profile_player_8"> | ||
| 300 | <property name="sizePolicy"> | ||
| 301 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 302 | <horstretch>0</horstretch> | ||
| 303 | <verstretch>0</verstretch> | ||
| 304 | </sizepolicy> | ||
| 305 | </property> | ||
| 306 | </widget> | ||
| 307 | </item> | ||
| 308 | </layout> | ||
| 309 | </widget> | ||
| 310 | </item> | ||
| 311 | </layout> | ||
| 312 | </widget> | ||
| 313 | </item> | ||
| 314 | </layout> | ||
| 315 | </item> | ||
| 316 | <item> | ||
| 317 | <spacer name="verticalSpacer"> | ||
| 318 | <property name="orientation"> | ||
| 319 | <enum>Qt::Vertical</enum> | ||
| 320 | </property> | ||
| 321 | <property name="sizeHint" stdset="0"> | ||
| 322 | <size> | ||
| 323 | <width>20</width> | ||
| 324 | <height>40</height> | ||
| 325 | </size> | ||
| 326 | </property> | ||
| 327 | </spacer> | ||
| 328 | </item> | ||
| 329 | </layout> | ||
| 330 | </widget> | ||
| 331 | <resources/> | ||
| 332 | <connections/> | ||
| 333 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 9e5a40fe7..b1575b0d3 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -855,8 +855,7 @@ void ConfigureInputPlayer::UpdateInputDeviceCombobox() { | |||
| 855 | return; | 855 | return; |
| 856 | } | 856 | } |
| 857 | 857 | ||
| 858 | const auto devices = | 858 | const auto devices = emulated_controller->GetMappedDevices(); |
| 859 | emulated_controller->GetMappedDevices(Core::HID::EmulatedDeviceIndex::AllDevices); | ||
| 860 | UpdateInputDevices(); | 859 | UpdateInputDevices(); |
| 861 | 860 | ||
| 862 | if (devices.empty()) { | 861 | if (devices.empty()) { |
| @@ -1553,6 +1552,7 @@ void ConfigureInputPlayer::LoadProfile() { | |||
| 1553 | } | 1552 | } |
| 1554 | 1553 | ||
| 1555 | void ConfigureInputPlayer::SaveProfile() { | 1554 | void ConfigureInputPlayer::SaveProfile() { |
| 1555 | static constexpr size_t HANDHELD_INDEX = 8; | ||
| 1556 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); | 1556 | const QString profile_name = ui->comboProfiles->itemText(ui->comboProfiles->currentIndex()); |
| 1557 | 1557 | ||
| 1558 | if (profile_name.isEmpty()) { | 1558 | if (profile_name.isEmpty()) { |
| @@ -1561,7 +1561,12 @@ void ConfigureInputPlayer::SaveProfile() { | |||
| 1561 | 1561 | ||
| 1562 | ApplyConfiguration(); | 1562 | ApplyConfiguration(); |
| 1563 | 1563 | ||
| 1564 | if (!profiles->SaveProfile(profile_name.toStdString(), player_index)) { | 1564 | // When we're in handheld mode, only the handheld emulated controller bindings are updated |
| 1565 | const bool is_handheld = player_index == 0 && emulated_controller->GetNpadIdType() == | ||
| 1566 | Core::HID::NpadIdType::Handheld; | ||
| 1567 | const auto profile_player_index = is_handheld ? HANDHELD_INDEX : player_index; | ||
| 1568 | |||
| 1569 | if (!profiles->SaveProfile(profile_name.toStdString(), profile_player_index)) { | ||
| 1565 | QMessageBox::critical(this, tr("Save Input Profile"), | 1570 | QMessageBox::critical(this, tr("Save Input Profile"), |
| 1566 | tr("Failed to save the input profile \"%1\"").arg(profile_name)); | 1571 | tr("Failed to save the input profile \"%1\"").arg(profile_name)); |
| 1567 | UpdateInputProfiles(); | 1572 | UpdateInputProfiles(); |
diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index 79434fdd8..26f60d121 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h | |||
| @@ -38,7 +38,7 @@ enum class InputType; | |||
| 38 | 38 | ||
| 39 | namespace Ui { | 39 | namespace Ui { |
| 40 | class ConfigureInputPlayer; | 40 | class ConfigureInputPlayer; |
| 41 | } | 41 | } // namespace Ui |
| 42 | 42 | ||
| 43 | namespace Core::HID { | 43 | namespace Core::HID { |
| 44 | class HIDCore; | 44 | class HIDCore; |
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index c3cb8f61d..93db47cfd 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #include "yuzu/configuration/configure_general.h" | 28 | #include "yuzu/configuration/configure_general.h" |
| 29 | #include "yuzu/configuration/configure_graphics.h" | 29 | #include "yuzu/configuration/configure_graphics.h" |
| 30 | #include "yuzu/configuration/configure_graphics_advanced.h" | 30 | #include "yuzu/configuration/configure_graphics_advanced.h" |
| 31 | #include "yuzu/configuration/configure_input.h" | 31 | #include "yuzu/configuration/configure_input_per_game.h" |
| 32 | #include "yuzu/configuration/configure_per_game.h" | 32 | #include "yuzu/configuration/configure_per_game.h" |
| 33 | #include "yuzu/configuration/configure_per_game_addons.h" | 33 | #include "yuzu/configuration/configure_per_game_addons.h" |
| 34 | #include "yuzu/configuration/configure_system.h" | 34 | #include "yuzu/configuration/configure_system.h" |
| @@ -50,6 +50,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st | |||
| 50 | general_tab = std::make_unique<ConfigureGeneral>(system_, this); | 50 | general_tab = std::make_unique<ConfigureGeneral>(system_, this); |
| 51 | graphics_tab = std::make_unique<ConfigureGraphics>(system_, this); | 51 | graphics_tab = std::make_unique<ConfigureGraphics>(system_, this); |
| 52 | graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); | 52 | graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); |
| 53 | input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this); | ||
| 53 | system_tab = std::make_unique<ConfigureSystem>(system_, this); | 54 | system_tab = std::make_unique<ConfigureSystem>(system_, this); |
| 54 | 55 | ||
| 55 | ui->setupUi(this); | 56 | ui->setupUi(this); |
| @@ -61,6 +62,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st | |||
| 61 | ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); | 62 | ui->tabWidget->addTab(graphics_tab.get(), tr("Graphics")); |
| 62 | ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics")); | 63 | ui->tabWidget->addTab(graphics_advanced_tab.get(), tr("Adv. Graphics")); |
| 63 | ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); | 64 | ui->tabWidget->addTab(audio_tab.get(), tr("Audio")); |
| 65 | ui->tabWidget->addTab(input_tab.get(), tr("Input Profiles")); | ||
| 64 | 66 | ||
| 65 | setFocusPolicy(Qt::ClickFocus); | 67 | setFocusPolicy(Qt::ClickFocus); |
| 66 | setWindowTitle(tr("Properties")); | 68 | setWindowTitle(tr("Properties")); |
| @@ -91,6 +93,7 @@ void ConfigurePerGame::ApplyConfiguration() { | |||
| 91 | graphics_tab->ApplyConfiguration(); | 93 | graphics_tab->ApplyConfiguration(); |
| 92 | graphics_advanced_tab->ApplyConfiguration(); | 94 | graphics_advanced_tab->ApplyConfiguration(); |
| 93 | audio_tab->ApplyConfiguration(); | 95 | audio_tab->ApplyConfiguration(); |
| 96 | input_tab->ApplyConfiguration(); | ||
| 94 | 97 | ||
| 95 | system.ApplySettings(); | 98 | system.ApplySettings(); |
| 96 | Settings::LogSettings(); | 99 | Settings::LogSettings(); |
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 17a98a0f3..4ecc43541 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h | |||
| @@ -16,12 +16,17 @@ namespace Core { | |||
| 16 | class System; | 16 | class System; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | namespace InputCommon { | ||
| 20 | class InputSubsystem; | ||
| 21 | } | ||
| 22 | |||
| 19 | class ConfigurePerGameAddons; | 23 | class ConfigurePerGameAddons; |
| 20 | class ConfigureAudio; | 24 | class ConfigureAudio; |
| 21 | class ConfigureCpu; | 25 | class ConfigureCpu; |
| 22 | class ConfigureGeneral; | 26 | class ConfigureGeneral; |
| 23 | class ConfigureGraphics; | 27 | class ConfigureGraphics; |
| 24 | class ConfigureGraphicsAdvanced; | 28 | class ConfigureGraphicsAdvanced; |
| 29 | class ConfigureInputPerGame; | ||
| 25 | class ConfigureSystem; | 30 | class ConfigureSystem; |
| 26 | 31 | ||
| 27 | class QGraphicsScene; | 32 | class QGraphicsScene; |
| @@ -72,5 +77,6 @@ private: | |||
| 72 | std::unique_ptr<ConfigureGeneral> general_tab; | 77 | std::unique_ptr<ConfigureGeneral> general_tab; |
| 73 | std::unique_ptr<ConfigureGraphics> graphics_tab; | 78 | std::unique_ptr<ConfigureGraphics> graphics_tab; |
| 74 | std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; | 79 | std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; |
| 80 | std::unique_ptr<ConfigureInputPerGame> input_tab; | ||
| 75 | std::unique_ptr<ConfigureSystem> system_tab; | 81 | std::unique_ptr<ConfigureSystem> system_tab; |
| 76 | }; | 82 | }; |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index c21153560..c0afb2e5f 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -126,6 +126,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 126 | #include "yuzu/compatibility_list.h" | 126 | #include "yuzu/compatibility_list.h" |
| 127 | #include "yuzu/configuration/config.h" | 127 | #include "yuzu/configuration/config.h" |
| 128 | #include "yuzu/configuration/configure_dialog.h" | 128 | #include "yuzu/configuration/configure_dialog.h" |
| 129 | #include "yuzu/configuration/configure_input_per_game.h" | ||
| 129 | #include "yuzu/debugger/console.h" | 130 | #include "yuzu/debugger/console.h" |
| 130 | #include "yuzu/debugger/controller.h" | 131 | #include "yuzu/debugger/controller.h" |
| 131 | #include "yuzu/debugger/profiler.h" | 132 | #include "yuzu/debugger/profiler.h" |
| @@ -1012,29 +1013,11 @@ void GMainWindow::InitializeWidgets() { | |||
| 1012 | renderer_status_button->setObjectName(QStringLiteral("RendererStatusBarButton")); | 1013 | renderer_status_button->setObjectName(QStringLiteral("RendererStatusBarButton")); |
| 1013 | renderer_status_button->setCheckable(true); | 1014 | renderer_status_button->setCheckable(true); |
| 1014 | renderer_status_button->setFocusPolicy(Qt::NoFocus); | 1015 | renderer_status_button->setFocusPolicy(Qt::NoFocus); |
| 1015 | connect(renderer_status_button, &QPushButton::toggled, [this](bool checked) { | 1016 | connect(renderer_status_button, &QPushButton::clicked, this, &GMainWindow::OnToggleGraphicsAPI); |
| 1016 | renderer_status_button->setText(checked ? tr("VULKAN") : tr("OPENGL")); | 1017 | UpdateAPIText(); |
| 1017 | }); | 1018 | renderer_status_button->setCheckable(true); |
| 1018 | renderer_status_button->toggle(); | ||
| 1019 | |||
| 1020 | renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == | 1019 | renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == |
| 1021 | Settings::RendererBackend::Vulkan); | 1020 | Settings::RendererBackend::Vulkan); |
| 1022 | connect(renderer_status_button, &QPushButton::clicked, [this] { | ||
| 1023 | if (emulation_running) { | ||
| 1024 | return; | ||
| 1025 | } | ||
| 1026 | if (renderer_status_button->isChecked()) { | ||
| 1027 | Settings::values.renderer_backend.SetValue(Settings::RendererBackend::Vulkan); | ||
| 1028 | } else { | ||
| 1029 | Settings::values.renderer_backend.SetValue(Settings::RendererBackend::OpenGL); | ||
| 1030 | if (Settings::values.scaling_filter.GetValue() == Settings::ScalingFilter::Fsr) { | ||
| 1031 | Settings::values.scaling_filter.SetValue(Settings::ScalingFilter::NearestNeighbor); | ||
| 1032 | UpdateFilterText(); | ||
| 1033 | } | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | system->ApplySettings(); | ||
| 1037 | }); | ||
| 1038 | statusBar()->insertPermanentWidget(0, renderer_status_button); | 1021 | statusBar()->insertPermanentWidget(0, renderer_status_button); |
| 1039 | 1022 | ||
| 1040 | statusBar()->setVisible(true); | 1023 | statusBar()->setVisible(true); |
| @@ -1676,6 +1659,11 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1676 | LOG_INFO(Frontend, "yuzu starting..."); | 1659 | LOG_INFO(Frontend, "yuzu starting..."); |
| 1677 | StoreRecentFile(filename); // Put the filename on top of the list | 1660 | StoreRecentFile(filename); // Put the filename on top of the list |
| 1678 | 1661 | ||
| 1662 | // Save configurations | ||
| 1663 | UpdateUISettings(); | ||
| 1664 | game_list->SaveInterfaceLayout(); | ||
| 1665 | config->Save(); | ||
| 1666 | |||
| 1679 | u64 title_id{0}; | 1667 | u64 title_id{0}; |
| 1680 | 1668 | ||
| 1681 | last_filename_booted = filename; | 1669 | last_filename_booted = filename; |
| @@ -1692,14 +1680,10 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t | |||
| 1692 | ? Common::FS::PathToUTF8String(file_path.filename()) | 1680 | ? Common::FS::PathToUTF8String(file_path.filename()) |
| 1693 | : fmt::format("{:016X}", title_id); | 1681 | : fmt::format("{:016X}", title_id); |
| 1694 | Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig); | 1682 | Config per_game_config(config_file_name, Config::ConfigType::PerGameConfig); |
| 1683 | system->HIDCore().ReloadInputDevices(); | ||
| 1695 | system->ApplySettings(); | 1684 | system->ApplySettings(); |
| 1696 | } | 1685 | } |
| 1697 | 1686 | ||
| 1698 | // Save configurations | ||
| 1699 | UpdateUISettings(); | ||
| 1700 | game_list->SaveInterfaceLayout(); | ||
| 1701 | config->Save(); | ||
| 1702 | |||
| 1703 | Settings::LogSettings(); | 1687 | Settings::LogSettings(); |
| 1704 | 1688 | ||
| 1705 | if (UISettings::values.select_user_on_boot) { | 1689 | if (UISettings::values.select_user_on_boot) { |
| @@ -2820,6 +2804,7 @@ void GMainWindow::OnStopGame() { | |||
| 2820 | ShutdownGame(); | 2804 | ShutdownGame(); |
| 2821 | 2805 | ||
| 2822 | Settings::RestoreGlobalState(system->IsPoweredOn()); | 2806 | Settings::RestoreGlobalState(system->IsPoweredOn()); |
| 2807 | system->HIDCore().ReloadInputDevices(); | ||
| 2823 | UpdateStatusButtons(); | 2808 | UpdateStatusButtons(); |
| 2824 | } | 2809 | } |
| 2825 | 2810 | ||
| @@ -2850,6 +2835,7 @@ void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_tex | |||
| 2850 | } | 2835 | } |
| 2851 | 2836 | ||
| 2852 | void GMainWindow::OnMenuReportCompatibility() { | 2837 | void GMainWindow::OnMenuReportCompatibility() { |
| 2838 | #if defined(ARCHITECTURE_x86_64) && !defined(__APPLE__) | ||
| 2853 | const auto& caps = Common::GetCPUCaps(); | 2839 | const auto& caps = Common::GetCPUCaps(); |
| 2854 | const bool has_fma = caps.fma || caps.fma4; | 2840 | const bool has_fma = caps.fma || caps.fma4; |
| 2855 | const auto processor_count = std::thread::hardware_concurrency(); | 2841 | const auto processor_count = std::thread::hardware_concurrency(); |
| @@ -2876,6 +2862,11 @@ void GMainWindow::OnMenuReportCompatibility() { | |||
| 2876 | "> " | 2862 | "> " |
| 2877 | "Web.")); | 2863 | "Web.")); |
| 2878 | } | 2864 | } |
| 2865 | #else | ||
| 2866 | QMessageBox::critical(this, tr("Hardware requirements not met"), | ||
| 2867 | tr("Your system does not meet the recommended hardware requirements. " | ||
| 2868 | "Compatibility reporting has been disabled.")); | ||
| 2869 | #endif | ||
| 2879 | } | 2870 | } |
| 2880 | 2871 | ||
| 2881 | void GMainWindow::OpenURL(const QUrl& url) { | 2872 | void GMainWindow::OpenURL(const QUrl& url) { |
| @@ -3253,6 +3244,18 @@ void GMainWindow::OnToggleAdaptingFilter() { | |||
| 3253 | UpdateFilterText(); | 3244 | UpdateFilterText(); |
| 3254 | } | 3245 | } |
| 3255 | 3246 | ||
| 3247 | void GMainWindow::OnToggleGraphicsAPI() { | ||
| 3248 | auto api = Settings::values.renderer_backend.GetValue(); | ||
| 3249 | if (api == Settings::RendererBackend::OpenGL) { | ||
| 3250 | api = Settings::RendererBackend::Vulkan; | ||
| 3251 | } else { | ||
| 3252 | api = Settings::RendererBackend::OpenGL; | ||
| 3253 | } | ||
| 3254 | Settings::values.renderer_backend.SetValue(api); | ||
| 3255 | renderer_status_button->setChecked(api == Settings::RendererBackend::Vulkan); | ||
| 3256 | UpdateAPIText(); | ||
| 3257 | } | ||
| 3258 | |||
| 3256 | void GMainWindow::OnConfigurePerGame() { | 3259 | void GMainWindow::OnConfigurePerGame() { |
| 3257 | const u64 title_id = system->GetCurrentProcessProgramID(); | 3260 | const u64 title_id = system->GetCurrentProcessProgramID(); |
| 3258 | OpenPerGameConfiguration(title_id, current_game_path.toStdString()); | 3261 | OpenPerGameConfiguration(title_id, current_game_path.toStdString()); |
| @@ -3281,6 +3284,7 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file | |||
| 3281 | // Do not cause the global config to write local settings into the config file | 3284 | // Do not cause the global config to write local settings into the config file |
| 3282 | const bool is_powered_on = system->IsPoweredOn(); | 3285 | const bool is_powered_on = system->IsPoweredOn(); |
| 3283 | Settings::RestoreGlobalState(is_powered_on); | 3286 | Settings::RestoreGlobalState(is_powered_on); |
| 3287 | system->HIDCore().ReloadInputDevices(); | ||
| 3284 | 3288 | ||
| 3285 | UISettings::values.configuration_applied = false; | 3289 | UISettings::values.configuration_applied = false; |
| 3286 | 3290 | ||
| @@ -3573,6 +3577,21 @@ void GMainWindow::UpdateDockedButton() { | |||
| 3573 | dock_status_button->setText(is_docked ? tr("DOCKED") : tr("HANDHELD")); | 3577 | dock_status_button->setText(is_docked ? tr("DOCKED") : tr("HANDHELD")); |
| 3574 | } | 3578 | } |
| 3575 | 3579 | ||
| 3580 | void GMainWindow::UpdateAPIText() { | ||
| 3581 | const auto api = Settings::values.renderer_backend.GetValue(); | ||
| 3582 | switch (api) { | ||
| 3583 | case Settings::RendererBackend::OpenGL: | ||
| 3584 | renderer_status_button->setText(tr("OPENGL")); | ||
| 3585 | break; | ||
| 3586 | case Settings::RendererBackend::Vulkan: | ||
| 3587 | renderer_status_button->setText(tr("VULKAN")); | ||
| 3588 | break; | ||
| 3589 | case Settings::RendererBackend::Null: | ||
| 3590 | renderer_status_button->setText(tr("NULL")); | ||
| 3591 | break; | ||
| 3592 | } | ||
| 3593 | } | ||
| 3594 | |||
| 3576 | void GMainWindow::UpdateFilterText() { | 3595 | void GMainWindow::UpdateFilterText() { |
| 3577 | const auto filter = Settings::values.scaling_filter.GetValue(); | 3596 | const auto filter = Settings::values.scaling_filter.GetValue(); |
| 3578 | switch (filter) { | 3597 | switch (filter) { |
| @@ -3618,6 +3637,7 @@ void GMainWindow::UpdateAAText() { | |||
| 3618 | void GMainWindow::UpdateStatusButtons() { | 3637 | void GMainWindow::UpdateStatusButtons() { |
| 3619 | renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == | 3638 | renderer_status_button->setChecked(Settings::values.renderer_backend.GetValue() == |
| 3620 | Settings::RendererBackend::Vulkan); | 3639 | Settings::RendererBackend::Vulkan); |
| 3640 | UpdateAPIText(); | ||
| 3621 | UpdateGPUAccuracyButton(); | 3641 | UpdateGPUAccuracyButton(); |
| 3622 | UpdateDockedButton(); | 3642 | UpdateDockedButton(); |
| 3623 | UpdateFilterText(); | 3643 | UpdateFilterText(); |
| @@ -3748,6 +3768,7 @@ void GMainWindow::OnCoreError(Core::SystemResultStatus result, std::string detai | |||
| 3748 | ShutdownGame(); | 3768 | ShutdownGame(); |
| 3749 | 3769 | ||
| 3750 | Settings::RestoreGlobalState(system->IsPoweredOn()); | 3770 | Settings::RestoreGlobalState(system->IsPoweredOn()); |
| 3771 | system->HIDCore().ReloadInputDevices(); | ||
| 3751 | UpdateStatusButtons(); | 3772 | UpdateStatusButtons(); |
| 3752 | } | 3773 | } |
| 3753 | } else { | 3774 | } else { |
| @@ -3899,18 +3920,19 @@ void GMainWindow::closeEvent(QCloseEvent* event) { | |||
| 3899 | // Unload controllers early | 3920 | // Unload controllers early |
| 3900 | controller_dialog->UnloadController(); | 3921 | controller_dialog->UnloadController(); |
| 3901 | game_list->UnloadController(); | 3922 | game_list->UnloadController(); |
| 3902 | system->HIDCore().UnloadInputDevices(); | ||
| 3903 | 3923 | ||
| 3904 | // Shutdown session if the emu thread is active... | 3924 | // Shutdown session if the emu thread is active... |
| 3905 | if (emu_thread != nullptr) { | 3925 | if (emu_thread != nullptr) { |
| 3906 | ShutdownGame(); | 3926 | ShutdownGame(); |
| 3907 | 3927 | ||
| 3908 | Settings::RestoreGlobalState(system->IsPoweredOn()); | 3928 | Settings::RestoreGlobalState(system->IsPoweredOn()); |
| 3929 | system->HIDCore().ReloadInputDevices(); | ||
| 3909 | UpdateStatusButtons(); | 3930 | UpdateStatusButtons(); |
| 3910 | } | 3931 | } |
| 3911 | 3932 | ||
| 3912 | render_window->close(); | 3933 | render_window->close(); |
| 3913 | multiplayer_state->Close(); | 3934 | multiplayer_state->Close(); |
| 3935 | system->HIDCore().UnloadInputDevices(); | ||
| 3914 | system->GetRoomNetwork().Shutdown(); | 3936 | system->GetRoomNetwork().Shutdown(); |
| 3915 | 3937 | ||
| 3916 | QWidget::closeEvent(event); | 3938 | QWidget::closeEvent(event); |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 4f9c3b450..62d629973 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -307,6 +307,7 @@ private slots: | |||
| 307 | void OnTasStartStop(); | 307 | void OnTasStartStop(); |
| 308 | void OnTasRecord(); | 308 | void OnTasRecord(); |
| 309 | void OnTasReset(); | 309 | void OnTasReset(); |
| 310 | void OnToggleGraphicsAPI(); | ||
| 310 | void OnToggleDockedMode(); | 311 | void OnToggleDockedMode(); |
| 311 | void OnToggleGpuAccuracy(); | 312 | void OnToggleGpuAccuracy(); |
| 312 | void OnToggleAdaptingFilter(); | 313 | void OnToggleAdaptingFilter(); |
| @@ -347,6 +348,7 @@ private: | |||
| 347 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, | 348 | void UpdateWindowTitle(std::string_view title_name = {}, std::string_view title_version = {}, |
| 348 | std::string_view gpu_vendor = {}); | 349 | std::string_view gpu_vendor = {}); |
| 349 | void UpdateDockedButton(); | 350 | void UpdateDockedButton(); |
| 351 | void UpdateAPIText(); | ||
| 350 | void UpdateFilterText(); | 352 | void UpdateFilterText(); |
| 351 | void UpdateAAText(); | 353 | void UpdateAAText(); |
| 352 | void UpdateStatusBar(); | 354 | void UpdateStatusBar(); |
diff --git a/src/yuzu/multiplayer/chat_room.h b/src/yuzu/multiplayer/chat_room.h index 01c70fad0..dd71ea4cd 100644 --- a/src/yuzu/multiplayer/chat_room.h +++ b/src/yuzu/multiplayer/chat_room.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <unordered_map> | ||
| 7 | #include <unordered_set> | 8 | #include <unordered_set> |
| 8 | #include <QDialog> | 9 | #include <QDialog> |
| 9 | #include <QSortFilterProxyModel> | 10 | #include <QSortFilterProxyModel> |
diff --git a/src/yuzu/precompiled_headers.h b/src/yuzu/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/yuzu/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp index ccdcf10fa..563818362 100644 --- a/src/yuzu/startup_checks.cpp +++ b/src/yuzu/startup_checks.cpp | |||
| @@ -27,7 +27,7 @@ void CheckVulkan() { | |||
| 27 | Vulkan::vk::InstanceDispatch dld; | 27 | Vulkan::vk::InstanceDispatch dld; |
| 28 | const Common::DynamicLibrary library = Vulkan::OpenLibrary(); | 28 | const Common::DynamicLibrary library = Vulkan::OpenLibrary(); |
| 29 | const Vulkan::vk::Instance instance = | 29 | const Vulkan::vk::Instance instance = |
| 30 | Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_0); | 30 | Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1); |
| 31 | 31 | ||
| 32 | } catch (const Vulkan::vk::Exception& exception) { | 32 | } catch (const Vulkan::vk::Exception& exception) { |
| 33 | fmt::print(stderr, "Failed to initialize Vulkan: {}\n", exception.what()); | 33 | fmt::print(stderr, "Failed to initialize Vulkan: {}\n", exception.what()); |
diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index 7d8ca3d8a..f6eeb9d8d 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt | |||
| @@ -22,8 +22,11 @@ add_executable(yuzu-cmd | |||
| 22 | emu_window/emu_window_sdl2.h | 22 | emu_window/emu_window_sdl2.h |
| 23 | emu_window/emu_window_sdl2_gl.cpp | 23 | emu_window/emu_window_sdl2_gl.cpp |
| 24 | emu_window/emu_window_sdl2_gl.h | 24 | emu_window/emu_window_sdl2_gl.h |
| 25 | emu_window/emu_window_sdl2_null.cpp | ||
| 26 | emu_window/emu_window_sdl2_null.h | ||
| 25 | emu_window/emu_window_sdl2_vk.cpp | 27 | emu_window/emu_window_sdl2_vk.cpp |
| 26 | emu_window/emu_window_sdl2_vk.h | 28 | emu_window/emu_window_sdl2_vk.h |
| 29 | precompiled_headers.h | ||
| 27 | yuzu.cpp | 30 | yuzu.cpp |
| 28 | yuzu.rc | 31 | yuzu.rc |
| 29 | ) | 32 | ) |
| @@ -31,21 +34,16 @@ add_executable(yuzu-cmd | |||
| 31 | create_target_directory_groups(yuzu-cmd) | 34 | create_target_directory_groups(yuzu-cmd) |
| 32 | 35 | ||
| 33 | target_link_libraries(yuzu-cmd PRIVATE common core input_common) | 36 | target_link_libraries(yuzu-cmd PRIVATE common core input_common) |
| 34 | target_link_libraries(yuzu-cmd PRIVATE inih glad) | 37 | target_link_libraries(yuzu-cmd PRIVATE inih::INIReader glad) |
| 35 | if (MSVC) | 38 | if (MSVC) |
| 36 | target_link_libraries(yuzu-cmd PRIVATE getopt) | 39 | target_link_libraries(yuzu-cmd PRIVATE getopt) |
| 37 | endif() | 40 | endif() |
| 38 | target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} SDL2 Threads::Threads) | 41 | target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) |
| 39 | 42 | ||
| 40 | create_resource("../../dist/yuzu.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon") | 43 | create_resource("../../dist/yuzu.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon") |
| 41 | target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR}) | 44 | target_include_directories(yuzu-cmd PRIVATE ${RESOURCES_DIR}) |
| 42 | 45 | ||
| 43 | target_include_directories(yuzu-cmd PRIVATE ../../externals/Vulkan-Headers/include) | 46 | target_link_libraries(yuzu-cmd PRIVATE SDL2::SDL2 Vulkan::Headers) |
| 44 | |||
| 45 | if (YUZU_USE_EXTERNAL_SDL2) | ||
| 46 | target_compile_definitions(yuzu-cmd PRIVATE -DYUZU_USE_EXTERNAL_SDL2) | ||
| 47 | target_include_directories(yuzu-cmd PRIVATE ${PROJECT_BINARY_DIR}/externals/SDL/include) | ||
| 48 | endif() | ||
| 49 | 47 | ||
| 50 | if(UNIX AND NOT APPLE) | 48 | if(UNIX AND NOT APPLE) |
| 51 | install(TARGETS yuzu-cmd) | 49 | install(TARGETS yuzu-cmd) |
| @@ -55,3 +53,7 @@ if (MSVC) | |||
| 55 | include(CopyYuzuSDLDeps) | 53 | include(CopyYuzuSDLDeps) |
| 56 | copy_yuzu_SDL_deps(yuzu-cmd) | 54 | copy_yuzu_SDL_deps(yuzu-cmd) |
| 57 | endif() | 55 | endif() |
| 56 | |||
| 57 | if (YUZU_USE_PRECOMPILED_HEADERS) | ||
| 58 | target_precompile_headers(yuzu-cmd PRIVATE precompiled_headers.h) | ||
| 59 | endif() | ||
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 59f9c8e09..de9b220da 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #pragma clang diagnostic pop | 15 | #pragma clang diagnostic pop |
| 16 | #endif | 16 | #endif |
| 17 | 17 | ||
| 18 | #include <inih/cpp/INIReader.h> | 18 | #include <INIReader.h> |
| 19 | #include "common/fs/file.h" | 19 | #include "common/fs/file.h" |
| 20 | #include "common/fs/fs.h" | 20 | #include "common/fs/fs.h" |
| 21 | #include "common/fs/path_util.h" | 21 | #include "common/fs/path_util.h" |
| @@ -286,6 +286,7 @@ void Config::ReadValues() { | |||
| 286 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem); | 286 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem); |
| 287 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); | 287 | ReadSetting("Cpu", Settings::values.cpuopt_fastmem_exclusives); |
| 288 | ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); | 288 | ReadSetting("Cpu", Settings::values.cpuopt_recompile_exclusives); |
| 289 | ReadSetting("Cpu", Settings::values.cpuopt_ignore_memory_aborts); | ||
| 289 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); | 290 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_unfuse_fma); |
| 290 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); | 291 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_reduce_fp_error); |
| 291 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); | 292 | ReadSetting("Cpu", Settings::values.cpuopt_unsafe_ignore_standard_fpcr); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 5bbc3f532..6fcf04e1b 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -208,6 +208,10 @@ cpuopt_fastmem_exclusives = | |||
| 208 | # 0: Disabled, 1 (default): Enabled | 208 | # 0: Disabled, 1 (default): Enabled |
| 209 | cpuopt_recompile_exclusives = | 209 | cpuopt_recompile_exclusives = |
| 210 | 210 | ||
| 211 | # Enable optimization to ignore invalid memory accesses (faster guest memory access) | ||
| 212 | # 0: Disabled, 1 (default): Enabled | ||
| 213 | cpuopt_ignore_memory_aborts = | ||
| 214 | |||
| 211 | # Enable unfuse FMA (improve performance on CPUs without FMA) | 215 | # Enable unfuse FMA (improve performance on CPUs without FMA) |
| 212 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. | 216 | # Only enabled if cpu_accuracy is set to Unsafe. Automatically chosen with cpu_accuracy = Auto-select. |
| 213 | # 0: Disabled, 1 (default): Enabled | 217 | # 0: Disabled, 1 (default): Enabled |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index 90bb0b415..25c23e2a5 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h | |||
| @@ -89,3 +89,5 @@ protected: | |||
| 89 | /// yuzu core instance | 89 | /// yuzu core instance |
| 90 | Core::System& system; | 90 | Core::System& system; |
| 91 | }; | 91 | }; |
| 92 | |||
| 93 | class DummyContext : public Core::Frontend::GraphicsContext {}; | ||
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp new file mode 100644 index 000000000..259192f3c --- /dev/null +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.cpp | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include <cstdlib> | ||
| 5 | #include <memory> | ||
| 6 | #include <string> | ||
| 7 | |||
| 8 | #include <fmt/format.h> | ||
| 9 | |||
| 10 | #include "common/logging/log.h" | ||
| 11 | #include "common/scm_rev.h" | ||
| 12 | #include "video_core/renderer_null/renderer_null.h" | ||
| 13 | #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" | ||
| 14 | |||
| 15 | #ifdef YUZU_USE_EXTERNAL_SDL2 | ||
| 16 | // Include this before SDL.h to prevent the external from including a dummy | ||
| 17 | #define USING_GENERATED_CONFIG_H | ||
| 18 | #include <SDL_config.h> | ||
| 19 | #endif | ||
| 20 | |||
| 21 | #include <SDL.h> | ||
| 22 | |||
| 23 | EmuWindow_SDL2_Null::EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, | ||
| 24 | Core::System& system_, bool fullscreen) | ||
| 25 | : EmuWindow_SDL2{input_subsystem_, system_} { | ||
| 26 | const std::string window_title = fmt::format("yuzu {} | {}-{} (Vulkan)", Common::g_build_name, | ||
| 27 | Common::g_scm_branch, Common::g_scm_desc); | ||
| 28 | render_window = | ||
| 29 | SDL_CreateWindow(window_title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, | ||
| 30 | Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height, | ||
| 31 | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI); | ||
| 32 | |||
| 33 | SetWindowIcon(); | ||
| 34 | |||
| 35 | if (fullscreen) { | ||
| 36 | Fullscreen(); | ||
| 37 | ShowCursor(false); | ||
| 38 | } | ||
| 39 | |||
| 40 | OnResize(); | ||
| 41 | OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); | ||
| 42 | SDL_PumpEvents(); | ||
| 43 | LOG_INFO(Frontend, "yuzu Version: {} | {}-{} (Null)", Common::g_build_name, | ||
| 44 | Common::g_scm_branch, Common::g_scm_desc); | ||
| 45 | } | ||
| 46 | |||
| 47 | EmuWindow_SDL2_Null::~EmuWindow_SDL2_Null() = default; | ||
| 48 | |||
| 49 | std::unique_ptr<Core::Frontend::GraphicsContext> EmuWindow_SDL2_Null::CreateSharedContext() const { | ||
| 50 | return std::make_unique<DummyContext>(); | ||
| 51 | } | ||
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h new file mode 100644 index 000000000..35aee286d --- /dev/null +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_null.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <memory> | ||
| 7 | |||
| 8 | #include "core/frontend/emu_window.h" | ||
| 9 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | ||
| 10 | |||
| 11 | namespace Core { | ||
| 12 | class System; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace InputCommon { | ||
| 16 | class InputSubsystem; | ||
| 17 | } | ||
| 18 | |||
| 19 | class EmuWindow_SDL2_Null final : public EmuWindow_SDL2 { | ||
| 20 | public: | ||
| 21 | explicit EmuWindow_SDL2_Null(InputCommon::InputSubsystem* input_subsystem_, | ||
| 22 | Core::System& system, bool fullscreen); | ||
| 23 | ~EmuWindow_SDL2_Null() override; | ||
| 24 | |||
| 25 | std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; | ||
| 26 | }; | ||
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp index 25948328c..9ed47d453 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp | |||
| @@ -12,12 +12,6 @@ | |||
| 12 | #include "video_core/renderer_vulkan/renderer_vulkan.h" | 12 | #include "video_core/renderer_vulkan/renderer_vulkan.h" |
| 13 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" | 13 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" |
| 14 | 14 | ||
| 15 | #ifdef YUZU_USE_EXTERNAL_SDL2 | ||
| 16 | // Include this before SDL.h to prevent the external from including a dummy | ||
| 17 | #define USING_GENERATED_CONFIG_H | ||
| 18 | #include <SDL_config.h> | ||
| 19 | #endif | ||
| 20 | |||
| 21 | #include <SDL.h> | 15 | #include <SDL.h> |
| 22 | #include <SDL_syswm.h> | 16 | #include <SDL_syswm.h> |
| 23 | 17 | ||
| @@ -51,11 +45,6 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste | |||
| 51 | window_info.type = Core::Frontend::WindowSystemType::Windows; | 45 | window_info.type = Core::Frontend::WindowSystemType::Windows; |
| 52 | window_info.render_surface = reinterpret_cast<void*>(wm.info.win.window); | 46 | window_info.render_surface = reinterpret_cast<void*>(wm.info.win.window); |
| 53 | break; | 47 | break; |
| 54 | #else | ||
| 55 | case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS: | ||
| 56 | LOG_CRITICAL(Frontend, "Window manager subsystem Windows not compiled"); | ||
| 57 | std::exit(EXIT_FAILURE); | ||
| 58 | break; | ||
| 59 | #endif | 48 | #endif |
| 60 | #ifdef SDL_VIDEO_DRIVER_X11 | 49 | #ifdef SDL_VIDEO_DRIVER_X11 |
| 61 | case SDL_SYSWM_TYPE::SDL_SYSWM_X11: | 50 | case SDL_SYSWM_TYPE::SDL_SYSWM_X11: |
| @@ -63,11 +52,6 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste | |||
| 63 | window_info.display_connection = wm.info.x11.display; | 52 | window_info.display_connection = wm.info.x11.display; |
| 64 | window_info.render_surface = reinterpret_cast<void*>(wm.info.x11.window); | 53 | window_info.render_surface = reinterpret_cast<void*>(wm.info.x11.window); |
| 65 | break; | 54 | break; |
| 66 | #else | ||
| 67 | case SDL_SYSWM_TYPE::SDL_SYSWM_X11: | ||
| 68 | LOG_CRITICAL(Frontend, "Window manager subsystem X11 not compiled"); | ||
| 69 | std::exit(EXIT_FAILURE); | ||
| 70 | break; | ||
| 71 | #endif | 55 | #endif |
| 72 | #ifdef SDL_VIDEO_DRIVER_WAYLAND | 56 | #ifdef SDL_VIDEO_DRIVER_WAYLAND |
| 73 | case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND: | 57 | case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND: |
| @@ -75,14 +59,21 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste | |||
| 75 | window_info.display_connection = wm.info.wl.display; | 59 | window_info.display_connection = wm.info.wl.display; |
| 76 | window_info.render_surface = wm.info.wl.surface; | 60 | window_info.render_surface = wm.info.wl.surface; |
| 77 | break; | 61 | break; |
| 78 | #else | 62 | #endif |
| 79 | case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND: | 63 | #ifdef SDL_VIDEO_DRIVER_COCOA |
| 80 | LOG_CRITICAL(Frontend, "Window manager subsystem Wayland not compiled"); | 64 | case SDL_SYSWM_TYPE::SDL_SYSWM_COCOA: |
| 81 | std::exit(EXIT_FAILURE); | 65 | window_info.type = Core::Frontend::WindowSystemType::Cocoa; |
| 66 | window_info.render_surface = SDL_Metal_CreateView(render_window); | ||
| 67 | break; | ||
| 68 | #endif | ||
| 69 | #ifdef SDL_VIDEO_DRIVER_ANDROID | ||
| 70 | case SDL_SYSWM_TYPE::SDL_SYSWM_ANDROID: | ||
| 71 | window_info.type = Core::Frontend::WindowSystemType::Android; | ||
| 72 | window_info.render_surface = reinterpret_cast<void*>(wm.info.android.window); | ||
| 82 | break; | 73 | break; |
| 83 | #endif | 74 | #endif |
| 84 | default: | 75 | default: |
| 85 | LOG_CRITICAL(Frontend, "Window manager subsystem not implemented"); | 76 | LOG_CRITICAL(Frontend, "Window manager subsystem {} not implemented", wm.subsystem); |
| 86 | std::exit(EXIT_FAILURE); | 77 | std::exit(EXIT_FAILURE); |
| 87 | break; | 78 | break; |
| 88 | } | 79 | } |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h index e39ad754d..9467d164a 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.h | |||
| @@ -24,5 +24,3 @@ public: | |||
| 24 | 24 | ||
| 25 | std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; | 25 | std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; |
| 26 | }; | 26 | }; |
| 27 | |||
| 28 | class DummyContext : public Core::Frontend::GraphicsContext {}; | ||
diff --git a/src/yuzu_cmd/precompiled_headers.h b/src/yuzu_cmd/precompiled_headers.h new file mode 100644 index 000000000..aabae730b --- /dev/null +++ b/src/yuzu_cmd/precompiled_headers.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: 2022 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/common_precompiled_headers.h" | ||
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index dfe5a30ea..a80649703 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "yuzu_cmd/config.h" | 34 | #include "yuzu_cmd/config.h" |
| 35 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" | 35 | #include "yuzu_cmd/emu_window/emu_window_sdl2.h" |
| 36 | #include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" | 36 | #include "yuzu_cmd/emu_window/emu_window_sdl2_gl.h" |
| 37 | #include "yuzu_cmd/emu_window/emu_window_sdl2_null.h" | ||
| 37 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" | 38 | #include "yuzu_cmd/emu_window/emu_window_sdl2_vk.h" |
| 38 | 39 | ||
| 39 | #ifdef _WIN32 | 40 | #ifdef _WIN32 |
| @@ -317,6 +318,9 @@ int main(int argc, char** argv) { | |||
| 317 | case Settings::RendererBackend::Vulkan: | 318 | case Settings::RendererBackend::Vulkan: |
| 318 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(&input_subsystem, system, fullscreen); | 319 | emu_window = std::make_unique<EmuWindow_SDL2_VK>(&input_subsystem, system, fullscreen); |
| 319 | break; | 320 | break; |
| 321 | case Settings::RendererBackend::Null: | ||
| 322 | emu_window = std::make_unique<EmuWindow_SDL2_Null>(&input_subsystem, system, fullscreen); | ||
| 323 | break; | ||
| 320 | } | 324 | } |
| 321 | 325 | ||
| 322 | system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); | 326 | system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); |