diff options
Diffstat (limited to 'src')
112 files changed, 1891 insertions, 851 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 50846a854..d64452617 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -180,11 +180,12 @@ ResultVal<std::vector<u8>> AudioRenderer::UpdateAudioRenderer(const std::vector< | |||
| 180 | 180 | ||
| 181 | // Copy output header | 181 | // Copy output header |
| 182 | UpdateDataHeader response_data{worker_params}; | 182 | UpdateDataHeader response_data{worker_params}; |
| 183 | std::vector<u8> output_params(response_data.total_size); | ||
| 184 | if (behavior_info.IsElapsedFrameCountSupported()) { | 183 | if (behavior_info.IsElapsedFrameCountSupported()) { |
| 185 | response_data.frame_count = 0x10; | 184 | response_data.render_info = sizeof(RendererInfo); |
| 186 | response_data.total_size += 0x10; | 185 | response_data.total_size += sizeof(RendererInfo); |
| 187 | } | 186 | } |
| 187 | |||
| 188 | std::vector<u8> output_params(response_data.total_size); | ||
| 188 | std::memcpy(output_params.data(), &response_data, sizeof(UpdateDataHeader)); | 189 | std::memcpy(output_params.data(), &response_data, sizeof(UpdateDataHeader)); |
| 189 | 190 | ||
| 190 | // Copy output memory pool entries | 191 | // Copy output memory pool entries |
| @@ -219,6 +220,17 @@ ResultVal<std::vector<u8>> AudioRenderer::UpdateAudioRenderer(const std::vector< | |||
| 219 | return Audren::ERR_INVALID_PARAMETERS; | 220 | return Audren::ERR_INVALID_PARAMETERS; |
| 220 | } | 221 | } |
| 221 | 222 | ||
| 223 | if (behavior_info.IsElapsedFrameCountSupported()) { | ||
| 224 | const std::size_t renderer_info_offset{ | ||
| 225 | sizeof(UpdateDataHeader) + response_data.memory_pools_size + response_data.voices_size + | ||
| 226 | response_data.effects_size + response_data.sinks_size + | ||
| 227 | response_data.performance_manager_size + response_data.behavior_size}; | ||
| 228 | RendererInfo renderer_info{}; | ||
| 229 | renderer_info.elasped_frame_count = elapsed_frame_count; | ||
| 230 | std::memcpy(output_params.data() + renderer_info_offset, &renderer_info, | ||
| 231 | sizeof(RendererInfo)); | ||
| 232 | } | ||
| 233 | |||
| 222 | return MakeResult(output_params); | 234 | return MakeResult(output_params); |
| 223 | } | 235 | } |
| 224 | 236 | ||
| @@ -447,6 +459,7 @@ void AudioRenderer::QueueMixedBuffer(Buffer::Tag tag) { | |||
| 447 | } | 459 | } |
| 448 | } | 460 | } |
| 449 | audio_out->QueueBuffer(stream, tag, std::move(buffer)); | 461 | audio_out->QueueBuffer(stream, tag, std::move(buffer)); |
| 462 | elapsed_frame_count++; | ||
| 450 | } | 463 | } |
| 451 | 464 | ||
| 452 | void AudioRenderer::ReleaseAndQueueBuffers() { | 465 | void AudioRenderer::ReleaseAndQueueBuffers() { |
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index 1f9114c07..f0b691a86 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h | |||
| @@ -196,6 +196,12 @@ struct EffectOutStatus { | |||
| 196 | }; | 196 | }; |
| 197 | static_assert(sizeof(EffectOutStatus) == 0x10, "EffectOutStatus is an invalid size"); | 197 | static_assert(sizeof(EffectOutStatus) == 0x10, "EffectOutStatus is an invalid size"); |
| 198 | 198 | ||
| 199 | struct RendererInfo { | ||
| 200 | u64_le elasped_frame_count{}; | ||
| 201 | INSERT_PADDING_WORDS(2); | ||
| 202 | }; | ||
| 203 | static_assert(sizeof(RendererInfo) == 0x10, "RendererInfo is an invalid size"); | ||
| 204 | |||
| 199 | struct UpdateDataHeader { | 205 | struct UpdateDataHeader { |
| 200 | UpdateDataHeader() {} | 206 | UpdateDataHeader() {} |
| 201 | 207 | ||
| @@ -209,7 +215,7 @@ struct UpdateDataHeader { | |||
| 209 | mixes_size = 0x0; | 215 | mixes_size = 0x0; |
| 210 | sinks_size = config.sink_count * 0x20; | 216 | sinks_size = config.sink_count * 0x20; |
| 211 | performance_manager_size = 0x10; | 217 | performance_manager_size = 0x10; |
| 212 | frame_count = 0; | 218 | render_info = 0; |
| 213 | total_size = sizeof(UpdateDataHeader) + behavior_size + memory_pools_size + voices_size + | 219 | total_size = sizeof(UpdateDataHeader) + behavior_size + memory_pools_size + voices_size + |
| 214 | effects_size + sinks_size + performance_manager_size; | 220 | effects_size + sinks_size + performance_manager_size; |
| 215 | } | 221 | } |
| @@ -223,8 +229,8 @@ struct UpdateDataHeader { | |||
| 223 | u32_le mixes_size{}; | 229 | u32_le mixes_size{}; |
| 224 | u32_le sinks_size{}; | 230 | u32_le sinks_size{}; |
| 225 | u32_le performance_manager_size{}; | 231 | u32_le performance_manager_size{}; |
| 226 | INSERT_PADDING_WORDS(1); | 232 | u32_le splitter_size{}; |
| 227 | u32_le frame_count{}; | 233 | u32_le render_info{}; |
| 228 | INSERT_PADDING_WORDS(4); | 234 | INSERT_PADDING_WORDS(4); |
| 229 | u32_le total_size{}; | 235 | u32_le total_size{}; |
| 230 | }; | 236 | }; |
| @@ -258,6 +264,7 @@ private: | |||
| 258 | std::unique_ptr<AudioOut> audio_out; | 264 | std::unique_ptr<AudioOut> audio_out; |
| 259 | StreamPtr stream; | 265 | StreamPtr stream; |
| 260 | Core::Memory::Memory& memory; | 266 | Core::Memory::Memory& memory; |
| 267 | std::size_t elapsed_frame_count{}; | ||
| 261 | }; | 268 | }; |
| 262 | 269 | ||
| 263 | } // namespace AudioCore | 270 | } // namespace AudioCore |
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 4ca98f8ea..ca7cfb030 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -67,7 +67,7 @@ s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const { | |||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { | 69 | static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { |
| 70 | const float volume{std::clamp(Settings::values.volume - (1.0f - game_volume), 0.0f, 1.0f)}; | 70 | const float volume{std::clamp(Settings::Volume() - (1.0f - game_volume), 0.0f, 1.0f)}; |
| 71 | 71 | ||
| 72 | if (volume == 1.0f) { | 72 | if (volume == 1.0f) { |
| 73 | return; | 73 | return; |
diff --git a/src/common/telemetry.cpp b/src/common/telemetry.cpp index 200c6489a..16d42facd 100644 --- a/src/common/telemetry.cpp +++ b/src/common/telemetry.cpp | |||
| @@ -60,6 +60,7 @@ void AppendCPUInfo(FieldCollection& fc) { | |||
| 60 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AES", Common::GetCPUCaps().aes); | 60 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AES", Common::GetCPUCaps().aes); |
| 61 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX", Common::GetCPUCaps().avx); | 61 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX", Common::GetCPUCaps().avx); |
| 62 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX2", Common::GetCPUCaps().avx2); | 62 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX2", Common::GetCPUCaps().avx2); |
| 63 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_AVX512", Common::GetCPUCaps().avx512); | ||
| 63 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI1", Common::GetCPUCaps().bmi1); | 64 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI1", Common::GetCPUCaps().bmi1); |
| 64 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI2", Common::GetCPUCaps().bmi2); | 65 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_BMI2", Common::GetCPUCaps().bmi2); |
| 65 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_FMA", Common::GetCPUCaps().fma); | 66 | fc.AddField(FieldType::UserSystem, "CPU_Extension_x64_FMA", Common::GetCPUCaps().fma); |
diff --git a/src/common/x64/cpu_detect.cpp b/src/common/x64/cpu_detect.cpp index d767c544c..fccd2eee5 100644 --- a/src/common/x64/cpu_detect.cpp +++ b/src/common/x64/cpu_detect.cpp | |||
| @@ -129,6 +129,11 @@ static CPUCaps Detect() { | |||
| 129 | caps.bmi1 = true; | 129 | caps.bmi1 = true; |
| 130 | if ((cpu_id[1] >> 8) & 1) | 130 | if ((cpu_id[1] >> 8) & 1) |
| 131 | caps.bmi2 = true; | 131 | caps.bmi2 = true; |
| 132 | // Checks for AVX512F, AVX512CD, AVX512VL, AVX512DQ, AVX512BW (Intel Skylake-X/SP) | ||
| 133 | if ((cpu_id[1] >> 16) & 1 && (cpu_id[1] >> 28) & 1 && (cpu_id[1] >> 31) & 1 && | ||
| 134 | (cpu_id[1] >> 17) & 1 && (cpu_id[1] >> 30) & 1) { | ||
| 135 | caps.avx512 = caps.avx2; | ||
| 136 | } | ||
| 132 | } | 137 | } |
| 133 | } | 138 | } |
| 134 | 139 | ||
diff --git a/src/common/x64/cpu_detect.h b/src/common/x64/cpu_detect.h index f0676fa5e..e3b63302e 100644 --- a/src/common/x64/cpu_detect.h +++ b/src/common/x64/cpu_detect.h | |||
| @@ -27,6 +27,7 @@ struct CPUCaps { | |||
| 27 | bool lzcnt; | 27 | bool lzcnt; |
| 28 | bool avx; | 28 | bool avx; |
| 29 | bool avx2; | 29 | bool avx2; |
| 30 | bool avx512; | ||
| 30 | bool bmi1; | 31 | bool bmi1; |
| 31 | bool bmi2; | 32 | bool bmi2; |
| 32 | bool fma; | 33 | bool fma; |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c0d068376..efbad628f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -608,11 +608,11 @@ endif() | |||
| 608 | create_target_directory_groups(core) | 608 | create_target_directory_groups(core) |
| 609 | 609 | ||
| 610 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) | 610 | target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) |
| 611 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus unicorn) | 611 | target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus unicorn zip) |
| 612 | 612 | ||
| 613 | if (YUZU_ENABLE_BOXCAT) | 613 | if (YUZU_ENABLE_BOXCAT) |
| 614 | target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) | 614 | target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) |
| 615 | target_link_libraries(core PRIVATE httplib nlohmann_json::nlohmann_json zip) | 615 | target_link_libraries(core PRIVATE httplib nlohmann_json::nlohmann_json) |
| 616 | endif() | 616 | endif() |
| 617 | 617 | ||
| 618 | if (ENABLE_WEB_SERVICE) | 618 | if (ENABLE_WEB_SERVICE) |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 19d798dc7..4c8663d03 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -62,7 +62,7 @@ public: | |||
| 62 | case Dynarmic::A32::Exception::Breakpoint: | 62 | case Dynarmic::A32::Exception::Breakpoint: |
| 63 | break; | 63 | break; |
| 64 | } | 64 | } |
| 65 | LOG_CRITICAL(HW_GPU, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", | 65 | LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", |
| 66 | static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); | 66 | static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); |
| 67 | UNIMPLEMENTED(); | 67 | UNIMPLEMENTED(); |
| 68 | } | 68 | } |
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 337b97be9..5f5e36d94 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -98,8 +98,8 @@ public: | |||
| 98 | } | 98 | } |
| 99 | [[fallthrough]]; | 99 | [[fallthrough]]; |
| 100 | default: | 100 | default: |
| 101 | ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:X})", | 101 | ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", |
| 102 | static_cast<std::size_t>(exception), pc); | 102 | static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); |
| 103 | } | 103 | } |
| 104 | } | 104 | } |
| 105 | 105 | ||
diff --git a/src/core/file_sys/system_archive/mii_model.cpp b/src/core/file_sys/system_archive/mii_model.cpp index 6a9add87c..61bb67945 100644 --- a/src/core/file_sys/system_archive/mii_model.cpp +++ b/src/core/file_sys/system_archive/mii_model.cpp | |||
| @@ -40,7 +40,7 @@ VirtualDir MiiModel() { | |||
| 40 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_MID.size()>>( | 40 | out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_MID.size()>>( |
| 41 | MiiModelData::SHAPE_MID, "ShapeMid.dat")); | 41 | MiiModelData::SHAPE_MID, "ShapeMid.dat")); |
| 42 | 42 | ||
| 43 | return std::move(out); | 43 | return out; |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | } // namespace FileSys::SystemArchive | 46 | } // namespace FileSys::SystemArchive |
diff --git a/src/core/file_sys/system_archive/shared_font.cpp b/src/core/file_sys/system_archive/shared_font.cpp index 2c05eb42e..c5cdf7d9b 100644 --- a/src/core/file_sys/system_archive/shared_font.cpp +++ b/src/core/file_sys/system_archive/shared_font.cpp | |||
| @@ -23,7 +23,7 @@ VirtualFile PackBFTTF(const std::array<u8, Size>& data, const std::string& name) | |||
| 23 | 23 | ||
| 24 | std::vector<u8> bfttf(Size + sizeof(u64)); | 24 | std::vector<u8> bfttf(Size + sizeof(u64)); |
| 25 | 25 | ||
| 26 | u64 offset = 0; | 26 | size_t offset = 0; |
| 27 | Service::NS::EncryptSharedFont(vec, bfttf, offset); | 27 | Service::NS::EncryptSharedFont(vec, bfttf, offset); |
| 28 | return std::make_shared<VectorVfsFile>(std::move(bfttf), name); | 28 | return std::make_shared<VectorVfsFile>(std::move(bfttf), name); |
| 29 | } | 29 | } |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index ba0eac4c2..0d01a7047 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -282,18 +282,18 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) { | |||
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { | 284 | std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { |
| 285 | std::vector<u8> buffer; | 285 | std::vector<u8> buffer{}; |
| 286 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 286 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && |
| 287 | BufferDescriptorA()[buffer_index].Size()}; | 287 | BufferDescriptorA()[buffer_index].Size()}; |
| 288 | 288 | ||
| 289 | if (is_buffer_a) { | 289 | if (is_buffer_a) { |
| 290 | ASSERT_MSG(BufferDescriptorA().size() > buffer_index, | 290 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return buffer; }, |
| 291 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | 291 | "BufferDescriptorA invalid buffer_index {}", buffer_index); |
| 292 | buffer.resize(BufferDescriptorA()[buffer_index].Size()); | 292 | buffer.resize(BufferDescriptorA()[buffer_index].Size()); |
| 293 | memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); | 293 | memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); |
| 294 | } else { | 294 | } else { |
| 295 | ASSERT_MSG(BufferDescriptorX().size() > buffer_index, | 295 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return buffer; }, |
| 296 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | 296 | "BufferDescriptorX invalid buffer_index {}", buffer_index); |
| 297 | buffer.resize(BufferDescriptorX()[buffer_index].Size()); | 297 | buffer.resize(BufferDescriptorX()[buffer_index].Size()); |
| 298 | memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); | 298 | memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); |
| 299 | } | 299 | } |
| @@ -318,16 +318,16 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, | |||
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | if (is_buffer_b) { | 320 | if (is_buffer_b) { |
| 321 | ASSERT_MSG(BufferDescriptorB().size() > buffer_index, | 321 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index && |
| 322 | "BufferDescriptorB invalid buffer_index {}", buffer_index); | 322 | BufferDescriptorB()[buffer_index].Size() >= size, |
| 323 | ASSERT_MSG(BufferDescriptorB()[buffer_index].Size() >= size, | 323 | { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", |
| 324 | "BufferDescriptorB buffer_index {} is not large enough", buffer_index); | 324 | buffer_index, size); |
| 325 | memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); | 325 | memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); |
| 326 | } else { | 326 | } else { |
| 327 | ASSERT_MSG(BufferDescriptorC().size() > buffer_index, | 327 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index && |
| 328 | "BufferDescriptorC invalid buffer_index {}", buffer_index); | 328 | BufferDescriptorC()[buffer_index].Size() >= size, |
| 329 | ASSERT_MSG(BufferDescriptorC()[buffer_index].Size() >= size, | 329 | { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", |
| 330 | "BufferDescriptorC buffer_index {} is not large enough", buffer_index); | 330 | buffer_index, size); |
| 331 | memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); | 331 | memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); |
| 332 | } | 332 | } |
| 333 | 333 | ||
| @@ -338,16 +338,12 @@ std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const | |||
| 338 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 338 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && |
| 339 | BufferDescriptorA()[buffer_index].Size()}; | 339 | BufferDescriptorA()[buffer_index].Size()}; |
| 340 | if (is_buffer_a) { | 340 | if (is_buffer_a) { |
| 341 | ASSERT_MSG(BufferDescriptorA().size() > buffer_index, | 341 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorA().size() > buffer_index, { return 0; }, |
| 342 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | 342 | "BufferDescriptorA invalid buffer_index {}", buffer_index); |
| 343 | ASSERT_MSG(BufferDescriptorA()[buffer_index].Size() > 0, | ||
| 344 | "BufferDescriptorA buffer_index {} is empty", buffer_index); | ||
| 345 | return BufferDescriptorA()[buffer_index].Size(); | 343 | return BufferDescriptorA()[buffer_index].Size(); |
| 346 | } else { | 344 | } else { |
| 347 | ASSERT_MSG(BufferDescriptorX().size() > buffer_index, | 345 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorX().size() > buffer_index, { return 0; }, |
| 348 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | 346 | "BufferDescriptorX invalid buffer_index {}", buffer_index); |
| 349 | ASSERT_MSG(BufferDescriptorX()[buffer_index].Size() > 0, | ||
| 350 | "BufferDescriptorX buffer_index {} is empty", buffer_index); | ||
| 351 | return BufferDescriptorX()[buffer_index].Size(); | 347 | return BufferDescriptorX()[buffer_index].Size(); |
| 352 | } | 348 | } |
| 353 | } | 349 | } |
| @@ -356,14 +352,15 @@ std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) cons | |||
| 356 | const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && | 352 | const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && |
| 357 | BufferDescriptorB()[buffer_index].Size()}; | 353 | BufferDescriptorB()[buffer_index].Size()}; |
| 358 | if (is_buffer_b) { | 354 | if (is_buffer_b) { |
| 359 | ASSERT_MSG(BufferDescriptorB().size() > buffer_index, | 355 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorB().size() > buffer_index, { return 0; }, |
| 360 | "BufferDescriptorB invalid buffer_index {}", buffer_index); | 356 | "BufferDescriptorB invalid buffer_index {}", buffer_index); |
| 361 | return BufferDescriptorB()[buffer_index].Size(); | 357 | return BufferDescriptorB()[buffer_index].Size(); |
| 362 | } else { | 358 | } else { |
| 363 | ASSERT_MSG(BufferDescriptorC().size() > buffer_index, | 359 | ASSERT_OR_EXECUTE_MSG(BufferDescriptorC().size() > buffer_index, { return 0; }, |
| 364 | "BufferDescriptorC invalid buffer_index {}", buffer_index); | 360 | "BufferDescriptorC invalid buffer_index {}", buffer_index); |
| 365 | return BufferDescriptorC()[buffer_index].Size(); | 361 | return BufferDescriptorC()[buffer_index].Size(); |
| 366 | } | 362 | } |
| 363 | return 0; | ||
| 367 | } | 364 | } |
| 368 | 365 | ||
| 369 | std::string HLERequestContext::Description() const { | 366 | std::string HLERequestContext::Description() const { |
diff --git a/src/core/hle/kernel/memory/memory_manager.cpp b/src/core/hle/kernel/memory/memory_manager.cpp index 6b432e1b2..acf13585c 100644 --- a/src/core/hle/kernel/memory/memory_manager.cpp +++ b/src/core/hle/kernel/memory/memory_manager.cpp | |||
| @@ -104,7 +104,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa | |||
| 104 | // Ensure that we don't leave anything un-freed | 104 | // Ensure that we don't leave anything un-freed |
| 105 | auto group_guard = detail::ScopeExit([&] { | 105 | auto group_guard = detail::ScopeExit([&] { |
| 106 | for (const auto& it : page_list.Nodes()) { | 106 | for (const auto& it : page_list.Nodes()) { |
| 107 | const auto min_num_pages{std::min( | 107 | const auto min_num_pages{std::min<size_t>( |
| 108 | it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)}; | 108 | it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)}; |
| 109 | chosen_manager.Free(it.GetAddress(), min_num_pages); | 109 | chosen_manager.Free(it.GetAddress(), min_num_pages); |
| 110 | } | 110 | } |
| @@ -139,7 +139,6 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | // Only succeed if we allocated as many pages as we wanted | 141 | // Only succeed if we allocated as many pages as we wanted |
| 142 | ASSERT(num_pages >= 0); | ||
| 143 | if (num_pages) { | 142 | if (num_pages) { |
| 144 | return ERR_OUT_OF_MEMORY; | 143 | return ERR_OUT_OF_MEMORY; |
| 145 | } | 144 | } |
| @@ -165,7 +164,7 @@ ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages, | |||
| 165 | 164 | ||
| 166 | // Free all of the pages | 165 | // Free all of the pages |
| 167 | for (const auto& it : page_list.Nodes()) { | 166 | for (const auto& it : page_list.Nodes()) { |
| 168 | const auto min_num_pages{std::min( | 167 | const auto min_num_pages{std::min<size_t>( |
| 169 | it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)}; | 168 | it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)}; |
| 170 | chosen_manager.Free(it.GetAddress(), min_num_pages); | 169 | chosen_manager.Free(it.GetAddress(), min_num_pages); |
| 171 | } | 170 | } |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 630a8b048..94d8c1fc6 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -44,6 +44,218 @@ static constexpr u32 SanitizeJPEGSize(std::size_t size) { | |||
| 44 | return static_cast<u32>(std::min(size, max_jpeg_image_size)); | 44 | return static_cast<u32>(std::min(size, max_jpeg_image_size)); |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> { | ||
| 48 | public: | ||
| 49 | explicit IManagerForSystemService(Common::UUID user_id) | ||
| 50 | : ServiceFramework("IManagerForSystemService") { | ||
| 51 | // clang-format off | ||
| 52 | static const FunctionInfo functions[] = { | ||
| 53 | {0, nullptr, "CheckAvailability"}, | ||
| 54 | {1, nullptr, "GetAccountId"}, | ||
| 55 | {2, nullptr, "EnsureIdTokenCacheAsync"}, | ||
| 56 | {3, nullptr, "LoadIdTokenCache"}, | ||
| 57 | {100, nullptr, "SetSystemProgramIdentification"}, | ||
| 58 | {101, nullptr, "RefreshNotificationTokenAsync"}, // 7.0.0+ | ||
| 59 | {110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+ | ||
| 60 | {111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+ | ||
| 61 | {112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0 | ||
| 62 | {113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+ | ||
| 63 | {120, nullptr, "GetNintendoAccountId"}, | ||
| 64 | {121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+ | ||
| 65 | {130, nullptr, "GetNintendoAccountUserResourceCache"}, | ||
| 66 | {131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"}, | ||
| 67 | {132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"}, | ||
| 68 | {133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+ | ||
| 69 | {134, nullptr, "RefreshNintendoAccountVerificationUrlCache"}, // 9.0.0+ | ||
| 70 | {135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+ | ||
| 71 | {140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+ | ||
| 72 | {141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+ | ||
| 73 | {142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+ | ||
| 74 | {150, nullptr, "CreateAuthorizationRequest"}, | ||
| 75 | }; | ||
| 76 | // clang-format on | ||
| 77 | |||
| 78 | RegisterHandlers(functions); | ||
| 79 | } | ||
| 80 | }; | ||
| 81 | |||
| 82 | // 3.0.0+ | ||
| 83 | class IFloatingRegistrationRequest final : public ServiceFramework<IFloatingRegistrationRequest> { | ||
| 84 | public: | ||
| 85 | explicit IFloatingRegistrationRequest(Common::UUID user_id) | ||
| 86 | : ServiceFramework("IFloatingRegistrationRequest") { | ||
| 87 | // clang-format off | ||
| 88 | static const FunctionInfo functions[] = { | ||
| 89 | {0, nullptr, "GetSessionId"}, | ||
| 90 | {12, nullptr, "GetAccountId"}, | ||
| 91 | {13, nullptr, "GetLinkedNintendoAccountId"}, | ||
| 92 | {14, nullptr, "GetNickname"}, | ||
| 93 | {15, nullptr, "GetProfileImage"}, | ||
| 94 | {21, nullptr, "LoadIdTokenCache"}, | ||
| 95 | {100, nullptr, "RegisterUser"}, // [1.0.0-3.0.2] RegisterAsync | ||
| 96 | {101, nullptr, "RegisterUserWithUid"}, // [1.0.0-3.0.2] RegisterWithUidAsync | ||
| 97 | {102, nullptr, "RegisterNetworkServiceAccountAsync"}, // 4.0.0+ | ||
| 98 | {103, nullptr, "RegisterNetworkServiceAccountWithUidAsync"}, // 4.0.0+ | ||
| 99 | {110, nullptr, "SetSystemProgramIdentification"}, | ||
| 100 | {111, nullptr, "EnsureIdTokenCacheAsync"}, | ||
| 101 | }; | ||
| 102 | // clang-format on | ||
| 103 | |||
| 104 | RegisterHandlers(functions); | ||
| 105 | } | ||
| 106 | }; | ||
| 107 | |||
| 108 | class IAdministrator final : public ServiceFramework<IAdministrator> { | ||
| 109 | public: | ||
| 110 | explicit IAdministrator(Common::UUID user_id) : ServiceFramework("IAdministrator") { | ||
| 111 | // clang-format off | ||
| 112 | static const FunctionInfo functions[] = { | ||
| 113 | {0, nullptr, "CheckAvailability"}, | ||
| 114 | {1, nullptr, "GetAccountId"}, | ||
| 115 | {2, nullptr, "EnsureIdTokenCacheAsync"}, | ||
| 116 | {3, nullptr, "LoadIdTokenCache"}, | ||
| 117 | {100, nullptr, "SetSystemProgramIdentification"}, | ||
| 118 | {101, nullptr, "RefreshNotificationTokenAsync"}, // 7.0.0+ | ||
| 119 | {110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+ | ||
| 120 | {111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+ | ||
| 121 | {112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0 | ||
| 122 | {113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+ | ||
| 123 | {120, nullptr, "GetNintendoAccountId"}, | ||
| 124 | {121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+ | ||
| 125 | {130, nullptr, "GetNintendoAccountUserResourceCache"}, | ||
| 126 | {131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"}, | ||
| 127 | {132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"}, | ||
| 128 | {133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+ | ||
| 129 | {134, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsync"}, // 9.0.0+ | ||
| 130 | {135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+ | ||
| 131 | {140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+ | ||
| 132 | {141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+ | ||
| 133 | {142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+ | ||
| 134 | {150, nullptr, "CreateAuthorizationRequest"}, | ||
| 135 | {200, nullptr, "IsRegistered"}, | ||
| 136 | {201, nullptr, "RegisterAsync"}, | ||
| 137 | {202, nullptr, "UnregisterAsync"}, | ||
| 138 | {203, nullptr, "DeleteRegistrationInfoLocally"}, | ||
| 139 | {220, nullptr, "SynchronizeProfileAsync"}, | ||
| 140 | {221, nullptr, "UploadProfileAsync"}, | ||
| 141 | {222, nullptr, "SynchronizaProfileAsyncIfSecondsElapsed"}, | ||
| 142 | {250, nullptr, "IsLinkedWithNintendoAccount"}, | ||
| 143 | {251, nullptr, "CreateProcedureToLinkWithNintendoAccount"}, | ||
| 144 | {252, nullptr, "ResumeProcedureToLinkWithNintendoAccount"}, | ||
| 145 | {255, nullptr, "CreateProcedureToUpdateLinkageStateOfNintendoAccount"}, | ||
| 146 | {256, nullptr, "ResumeProcedureToUpdateLinkageStateOfNintendoAccount"}, | ||
| 147 | {260, nullptr, "CreateProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+ | ||
| 148 | {261, nullptr, "ResumeProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+ | ||
| 149 | {280, nullptr, "ProxyProcedureToAcquireApplicationAuthorizationForNintendoAccount"}, | ||
| 150 | {290, nullptr, "GetRequestForNintendoAccountUserResourceView"}, // 8.0.0+ | ||
| 151 | {300, nullptr, "TryRecoverNintendoAccountUserStateAsync"}, // 6.0.0+ | ||
| 152 | {400, nullptr, "IsServiceEntryRequirementCacheRefreshRequiredForOnlinePlay"}, // 6.1.0+ | ||
| 153 | {401, nullptr, "RefreshServiceEntryRequirementCacheForOnlinePlayAsync"}, // 6.1.0+ | ||
| 154 | {900, nullptr, "GetAuthenticationInfoForWin"}, // 9.0.0+ | ||
| 155 | {901, nullptr, "ImportAsyncForWin"}, // 9.0.0+ | ||
| 156 | {997, nullptr, "DebugUnlinkNintendoAccountAsync"}, | ||
| 157 | {998, nullptr, "DebugSetAvailabilityErrorDetail"}, | ||
| 158 | }; | ||
| 159 | // clang-format on | ||
| 160 | |||
| 161 | RegisterHandlers(functions); | ||
| 162 | } | ||
| 163 | }; | ||
| 164 | |||
| 165 | class IAuthorizationRequest final : public ServiceFramework<IAuthorizationRequest> { | ||
| 166 | public: | ||
| 167 | explicit IAuthorizationRequest(Common::UUID user_id) | ||
| 168 | : ServiceFramework("IAuthorizationRequest") { | ||
| 169 | // clang-format off | ||
| 170 | static const FunctionInfo functions[] = { | ||
| 171 | {0, nullptr, "GetSessionId"}, | ||
| 172 | {10, nullptr, "InvokeWithoutInteractionAsync"}, | ||
| 173 | {19, nullptr, "IsAuthorized"}, | ||
| 174 | {20, nullptr, "GetAuthorizationCode"}, | ||
| 175 | {21, nullptr, "GetIdToken"}, | ||
| 176 | {22, nullptr, "GetState"}, | ||
| 177 | }; | ||
| 178 | // clang-format on | ||
| 179 | |||
| 180 | RegisterHandlers(functions); | ||
| 181 | } | ||
| 182 | }; | ||
| 183 | |||
| 184 | class IOAuthProcedure final : public ServiceFramework<IOAuthProcedure> { | ||
| 185 | public: | ||
| 186 | explicit IOAuthProcedure(Common::UUID user_id) : ServiceFramework("IOAuthProcedure") { | ||
| 187 | // clang-format off | ||
| 188 | static const FunctionInfo functions[] = { | ||
| 189 | {0, nullptr, "PrepareAsync"}, | ||
| 190 | {1, nullptr, "GetRequest"}, | ||
| 191 | {2, nullptr, "ApplyResponse"}, | ||
| 192 | {3, nullptr, "ApplyResponseAsync"}, | ||
| 193 | {10, nullptr, "Suspend"}, | ||
| 194 | }; | ||
| 195 | // clang-format on | ||
| 196 | |||
| 197 | RegisterHandlers(functions); | ||
| 198 | } | ||
| 199 | }; | ||
| 200 | |||
| 201 | // 3.0.0+ | ||
| 202 | class IOAuthProcedureForExternalNsa final : public ServiceFramework<IOAuthProcedureForExternalNsa> { | ||
| 203 | public: | ||
| 204 | explicit IOAuthProcedureForExternalNsa(Common::UUID user_id) | ||
| 205 | : ServiceFramework("IOAuthProcedureForExternalNsa") { | ||
| 206 | // clang-format off | ||
| 207 | static const FunctionInfo functions[] = { | ||
| 208 | {0, nullptr, "PrepareAsync"}, | ||
| 209 | {1, nullptr, "GetRequest"}, | ||
| 210 | {2, nullptr, "ApplyResponse"}, | ||
| 211 | {3, nullptr, "ApplyResponseAsync"}, | ||
| 212 | {10, nullptr, "Suspend"}, | ||
| 213 | {100, nullptr, "GetAccountId"}, | ||
| 214 | {101, nullptr, "GetLinkedNintendoAccountId"}, | ||
| 215 | {102, nullptr, "GetNickname"}, | ||
| 216 | {103, nullptr, "GetProfileImage"}, | ||
| 217 | }; | ||
| 218 | // clang-format on | ||
| 219 | |||
| 220 | RegisterHandlers(functions); | ||
| 221 | } | ||
| 222 | }; | ||
| 223 | |||
| 224 | class IOAuthProcedureForNintendoAccountLinkage final | ||
| 225 | : public ServiceFramework<IOAuthProcedureForNintendoAccountLinkage> { | ||
| 226 | public: | ||
| 227 | explicit IOAuthProcedureForNintendoAccountLinkage(Common::UUID user_id) | ||
| 228 | : ServiceFramework("IOAuthProcedureForNintendoAccountLinkage") { | ||
| 229 | // clang-format off | ||
| 230 | static const FunctionInfo functions[] = { | ||
| 231 | {0, nullptr, "PrepareAsync"}, | ||
| 232 | {1, nullptr, "GetRequest"}, | ||
| 233 | {2, nullptr, "ApplyResponse"}, | ||
| 234 | {3, nullptr, "ApplyResponseAsync"}, | ||
| 235 | {10, nullptr, "Suspend"}, | ||
| 236 | {100, nullptr, "GetRequestWithTheme"}, | ||
| 237 | {101, nullptr, "IsNetworkServiceAccountReplaced"}, | ||
| 238 | {199, nullptr, "GetUrlForIntroductionOfExtraMembership"}, // 2.0.0 - 5.1.0 | ||
| 239 | }; | ||
| 240 | // clang-format on | ||
| 241 | |||
| 242 | RegisterHandlers(functions); | ||
| 243 | } | ||
| 244 | }; | ||
| 245 | |||
| 246 | class INotifier final : public ServiceFramework<INotifier> { | ||
| 247 | public: | ||
| 248 | explicit INotifier(Common::UUID user_id) : ServiceFramework("INotifier") { | ||
| 249 | // clang-format off | ||
| 250 | static const FunctionInfo functions[] = { | ||
| 251 | {0, nullptr, "GetSystemEvent"}, | ||
| 252 | }; | ||
| 253 | // clang-format on | ||
| 254 | |||
| 255 | RegisterHandlers(functions); | ||
| 256 | } | ||
| 257 | }; | ||
| 258 | |||
| 47 | class IProfileCommon : public ServiceFramework<IProfileCommon> { | 259 | class IProfileCommon : public ServiceFramework<IProfileCommon> { |
| 48 | public: | 260 | public: |
| 49 | explicit IProfileCommon(const char* name, bool editor_commands, Common::UUID user_id, | 261 | explicit IProfileCommon(const char* name, bool editor_commands, Common::UUID user_id, |
| @@ -226,6 +438,54 @@ public: | |||
| 226 | : IProfileCommon("IProfileEditor", true, user_id, profile_manager) {} | 438 | : IProfileCommon("IProfileEditor", true, user_id, profile_manager) {} |
| 227 | }; | 439 | }; |
| 228 | 440 | ||
| 441 | class IAsyncContext final : public ServiceFramework<IAsyncContext> { | ||
| 442 | public: | ||
| 443 | explicit IAsyncContext(Common::UUID user_id) : ServiceFramework("IAsyncContext") { | ||
| 444 | // clang-format off | ||
| 445 | static const FunctionInfo functions[] = { | ||
| 446 | {0, nullptr, "GetSystemEvent"}, | ||
| 447 | {1, nullptr, "Cancel"}, | ||
| 448 | {2, nullptr, "HasDone"}, | ||
| 449 | {3, nullptr, "GetResult"}, | ||
| 450 | }; | ||
| 451 | // clang-format on | ||
| 452 | |||
| 453 | RegisterHandlers(functions); | ||
| 454 | } | ||
| 455 | }; | ||
| 456 | |||
| 457 | class ISessionObject final : public ServiceFramework<ISessionObject> { | ||
| 458 | public: | ||
| 459 | explicit ISessionObject(Common::UUID user_id) : ServiceFramework("ISessionObject") { | ||
| 460 | // clang-format off | ||
| 461 | static const FunctionInfo functions[] = { | ||
| 462 | {999, nullptr, "Dummy"}, | ||
| 463 | }; | ||
| 464 | // clang-format on | ||
| 465 | |||
| 466 | RegisterHandlers(functions); | ||
| 467 | } | ||
| 468 | }; | ||
| 469 | |||
| 470 | class IGuestLoginRequest final : public ServiceFramework<IGuestLoginRequest> { | ||
| 471 | public: | ||
| 472 | explicit IGuestLoginRequest(Common::UUID) : ServiceFramework("IGuestLoginRequest") { | ||
| 473 | // clang-format off | ||
| 474 | static const FunctionInfo functions[] = { | ||
| 475 | {0, nullptr, "GetSessionId"}, | ||
| 476 | {11, nullptr, "Unknown"}, // 1.0.0 - 2.3.0 (the name is blank on Switchbrew) | ||
| 477 | {12, nullptr, "GetAccountId"}, | ||
| 478 | {13, nullptr, "GetLinkedNintendoAccountId"}, | ||
| 479 | {14, nullptr, "GetNickname"}, | ||
| 480 | {15, nullptr, "GetProfileImage"}, | ||
| 481 | {21, nullptr, "LoadIdTokenCache"}, // 3.0.0+ | ||
| 482 | }; | ||
| 483 | // clang-format on | ||
| 484 | |||
| 485 | RegisterHandlers(functions); | ||
| 486 | } | ||
| 487 | }; | ||
| 488 | |||
| 229 | class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { | 489 | class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { |
| 230 | public: | 490 | public: |
| 231 | explicit IManagerForApplication(Common::UUID user_id) | 491 | explicit IManagerForApplication(Common::UUID user_id) |
| @@ -265,6 +525,87 @@ private: | |||
| 265 | Common::UUID user_id; | 525 | Common::UUID user_id; |
| 266 | }; | 526 | }; |
| 267 | 527 | ||
| 528 | // 6.0.0+ | ||
| 529 | class IAsyncNetworkServiceLicenseKindContext final | ||
| 530 | : public ServiceFramework<IAsyncNetworkServiceLicenseKindContext> { | ||
| 531 | public: | ||
| 532 | explicit IAsyncNetworkServiceLicenseKindContext(Common::UUID user_id) | ||
| 533 | : ServiceFramework("IAsyncNetworkServiceLicenseKindContext") { | ||
| 534 | // clang-format off | ||
| 535 | static const FunctionInfo functions[] = { | ||
| 536 | {0, nullptr, "GetSystemEvent"}, | ||
| 537 | {1, nullptr, "Cancel"}, | ||
| 538 | {2, nullptr, "HasDone"}, | ||
| 539 | {3, nullptr, "GetResult"}, | ||
| 540 | {4, nullptr, "GetNetworkServiceLicenseKind"}, | ||
| 541 | }; | ||
| 542 | // clang-format on | ||
| 543 | |||
| 544 | RegisterHandlers(functions); | ||
| 545 | } | ||
| 546 | }; | ||
| 547 | |||
| 548 | // 8.0.0+ | ||
| 549 | class IOAuthProcedureForUserRegistration final | ||
| 550 | : public ServiceFramework<IOAuthProcedureForUserRegistration> { | ||
| 551 | public: | ||
| 552 | explicit IOAuthProcedureForUserRegistration(Common::UUID user_id) | ||
| 553 | : ServiceFramework("IOAuthProcedureForUserRegistration") { | ||
| 554 | // clang-format off | ||
| 555 | static const FunctionInfo functions[] = { | ||
| 556 | {0, nullptr, "PrepareAsync"}, | ||
| 557 | {1, nullptr, "GetRequest"}, | ||
| 558 | {2, nullptr, "ApplyResponse"}, | ||
| 559 | {3, nullptr, "ApplyResponseAsync"}, | ||
| 560 | {10, nullptr, "Suspend"}, | ||
| 561 | {100, nullptr, "GetAccountId"}, | ||
| 562 | {101, nullptr, "GetLinkedNintendoAccountId"}, | ||
| 563 | {102, nullptr, "GetNickname"}, | ||
| 564 | {103, nullptr, "GetProfileImage"}, | ||
| 565 | {110, nullptr, "RegisterUserAsync"}, | ||
| 566 | {111, nullptr, "GetUid"}, | ||
| 567 | }; | ||
| 568 | // clang-format on | ||
| 569 | |||
| 570 | RegisterHandlers(functions); | ||
| 571 | } | ||
| 572 | }; | ||
| 573 | |||
| 574 | class DAUTH_O final : public ServiceFramework<DAUTH_O> { | ||
| 575 | public: | ||
| 576 | explicit DAUTH_O(Common::UUID) : ServiceFramework("dauth:o") { | ||
| 577 | // clang-format off | ||
| 578 | static const FunctionInfo functions[] = { | ||
| 579 | {0, nullptr, "EnsureAuthenticationTokenCacheAsync"}, // [5.0.0-5.1.0] GeneratePostData | ||
| 580 | {1, nullptr, "LoadAuthenticationTokenCache"}, // 6.0.0+ | ||
| 581 | {2, nullptr, "InvalidateAuthenticationTokenCache"}, // 6.0.0+ | ||
| 582 | {10, nullptr, "EnsureEdgeTokenCacheAsync"}, // 6.0.0+ | ||
| 583 | {11, nullptr, "LoadEdgeTokenCache"}, // 6.0.0+ | ||
| 584 | {12, nullptr, "InvalidateEdgeTokenCache"}, // 6.0.0+ | ||
| 585 | }; | ||
| 586 | // clang-format on | ||
| 587 | |||
| 588 | RegisterHandlers(functions); | ||
| 589 | } | ||
| 590 | }; | ||
| 591 | |||
| 592 | // 6.0.0+ | ||
| 593 | class IAsyncResult final : public ServiceFramework<IAsyncResult> { | ||
| 594 | public: | ||
| 595 | explicit IAsyncResult(Common::UUID user_id) : ServiceFramework("IAsyncResult") { | ||
| 596 | // clang-format off | ||
| 597 | static const FunctionInfo functions[] = { | ||
| 598 | {0, nullptr, "GetResult"}, | ||
| 599 | {1, nullptr, "Cancel"}, | ||
| 600 | {2, nullptr, "IsAvailable"}, | ||
| 601 | {3, nullptr, "GetSystemEvent"}, | ||
| 602 | }; | ||
| 603 | // clang-format on | ||
| 604 | |||
| 605 | RegisterHandlers(functions); | ||
| 606 | } | ||
| 607 | }; | ||
| 608 | |||
| 268 | void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) { | 609 | void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) { |
| 269 | LOG_DEBUG(Service_ACC, "called"); | 610 | LOG_DEBUG(Service_ACC, "called"); |
| 270 | IPC::ResponseBuilder rb{ctx, 3}; | 611 | IPC::ResponseBuilder rb{ctx, 3}; |
diff --git a/src/core/hle/service/acc/acc_aa.cpp b/src/core/hle/service/acc/acc_aa.cpp index 3bac6bcd1..51f119b12 100644 --- a/src/core/hle/service/acc/acc_aa.cpp +++ b/src/core/hle/service/acc/acc_aa.cpp | |||
| @@ -13,8 +13,8 @@ ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 13 | {0, nullptr, "EnsureCacheAsync"}, | 13 | {0, nullptr, "EnsureCacheAsync"}, |
| 14 | {1, nullptr, "LoadCache"}, | 14 | {1, nullptr, "LoadCache"}, |
| 15 | {2, nullptr, "GetDeviceAccountId"}, | 15 | {2, nullptr, "GetDeviceAccountId"}, |
| 16 | {50, nullptr, "RegisterNotificationTokenAsync"}, | 16 | {50, nullptr, "RegisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0 |
| 17 | {51, nullptr, "UnregisterNotificationTokenAsync"}, | 17 | {51, nullptr, "UnregisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0 |
| 18 | }; | 18 | }; |
| 19 | RegisterHandlers(functions); | 19 | RegisterHandlers(functions); |
| 20 | } | 20 | } |
diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index 2eefc6df5..85620bde3 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp | |||
| @@ -17,28 +17,28 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 17 | {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"}, | 17 | {3, &ACC_SU::ListOpenUsers, "ListOpenUsers"}, |
| 18 | {4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"}, | 18 | {4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"}, |
| 19 | {5, &ACC_SU::GetProfile, "GetProfile"}, | 19 | {5, &ACC_SU::GetProfile, "GetProfile"}, |
| 20 | {6, nullptr, "GetProfileDigest"}, | 20 | {6, nullptr, "GetProfileDigest"}, // 3.0.0+ |
| 21 | {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, | 21 | {50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, |
| 22 | {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, | 22 | {51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, |
| 23 | {60, nullptr, "ListOpenContextStoredUsers"}, | 23 | {60, nullptr, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0 |
| 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, | 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+ |
| 25 | {100, nullptr, "GetUserRegistrationNotifier"}, | 25 | {100, nullptr, "GetUserRegistrationNotifier"}, |
| 26 | {101, nullptr, "GetUserStateChangeNotifier"}, | 26 | {101, nullptr, "GetUserStateChangeNotifier"}, |
| 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, | 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, |
| 28 | {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, | 28 | {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, |
| 29 | {104, nullptr, "GetProfileUpdateNotifier"}, | 29 | {104, nullptr, "GetProfileUpdateNotifier"}, |
| 30 | {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, | 30 | {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+ |
| 31 | {106, nullptr, "GetProfileSyncNotifier"}, | 31 | {106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+ |
| 32 | {110, nullptr, "StoreSaveDataThumbnail"}, | 32 | {110, nullptr, "StoreSaveDataThumbnail"}, |
| 33 | {111, nullptr, "ClearSaveDataThumbnail"}, | 33 | {111, nullptr, "ClearSaveDataThumbnail"}, |
| 34 | {112, nullptr, "LoadSaveDataThumbnail"}, | 34 | {112, nullptr, "LoadSaveDataThumbnail"}, |
| 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, | 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+ |
| 36 | {120, nullptr, "ListOpenUsersInApplication"}, | 36 | {120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+ |
| 37 | {130, nullptr, "ActivateOpenContextRetention"}, | 37 | {130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+ |
| 38 | {140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"}, | 38 | {140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ |
| 39 | {150, nullptr, "AuthenticateApplicationAsync"}, | 39 | {150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+ |
| 40 | {190, nullptr, "GetUserLastOpenedApplication"}, | 40 | {190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0 |
| 41 | {191, nullptr, "ActivateOpenContextHolder"}, | 41 | {191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+ |
| 42 | {200, nullptr, "BeginUserRegistration"}, | 42 | {200, nullptr, "BeginUserRegistration"}, |
| 43 | {201, nullptr, "CompleteUserRegistration"}, | 43 | {201, nullptr, "CompleteUserRegistration"}, |
| 44 | {202, nullptr, "CancelUserRegistration"}, | 44 | {202, nullptr, "CancelUserRegistration"}, |
| @@ -46,15 +46,15 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 46 | {204, nullptr, "SetUserPosition"}, | 46 | {204, nullptr, "SetUserPosition"}, |
| 47 | {205, &ACC_SU::GetProfileEditor, "GetProfileEditor"}, | 47 | {205, &ACC_SU::GetProfileEditor, "GetProfileEditor"}, |
| 48 | {206, nullptr, "CompleteUserRegistrationForcibly"}, | 48 | {206, nullptr, "CompleteUserRegistrationForcibly"}, |
| 49 | {210, nullptr, "CreateFloatingRegistrationRequest"}, | 49 | {210, nullptr, "CreateFloatingRegistrationRequest"}, // 3.0.0+ |
| 50 | {211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"}, | 50 | {211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+ |
| 51 | {212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"}, | 51 | {212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+ |
| 52 | {230, nullptr, "AuthenticateServiceAsync"}, | 52 | {230, nullptr, "AuthenticateServiceAsync"}, |
| 53 | {250, nullptr, "GetBaasAccountAdministrator"}, | 53 | {250, nullptr, "GetBaasAccountAdministrator"}, |
| 54 | {290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"}, | 54 | {290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"}, |
| 55 | {291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"}, | 55 | {291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"}, // 3.0.0+ |
| 56 | {299, nullptr, "SuspendBackgroundDaemon"}, | 56 | {299, nullptr, "SuspendBackgroundDaemon"}, |
| 57 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, | 57 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+ |
| 58 | {998, nullptr, "DebugSetUserStateClose"}, | 58 | {998, nullptr, "DebugSetUserStateClose"}, |
| 59 | {999, nullptr, "DebugSetUserStateOpen"}, | 59 | {999, nullptr, "DebugSetUserStateOpen"}, |
| 60 | }; | 60 | }; |
diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index fb4e7e772..49f6e20f1 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp | |||
| @@ -17,23 +17,23 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 17 | {3, &ACC_U0::ListOpenUsers, "ListOpenUsers"}, | 17 | {3, &ACC_U0::ListOpenUsers, "ListOpenUsers"}, |
| 18 | {4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"}, | 18 | {4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"}, |
| 19 | {5, &ACC_U0::GetProfile, "GetProfile"}, | 19 | {5, &ACC_U0::GetProfile, "GetProfile"}, |
| 20 | {6, nullptr, "GetProfileDigest"}, | 20 | {6, nullptr, "GetProfileDigest"}, // 3.0.0+ |
| 21 | {50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, | 21 | {50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, |
| 22 | {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, | 22 | {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, |
| 23 | {60, nullptr, "ListOpenContextStoredUsers"}, | 23 | {60, nullptr, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0 |
| 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, | 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+ |
| 25 | {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, | 25 | {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, |
| 26 | {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"}, | 26 | {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"}, |
| 27 | {102, nullptr, "AuthenticateApplicationAsync"}, | 27 | {102, nullptr, "AuthenticateApplicationAsync"}, |
| 28 | {103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, | 28 | {103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+ |
| 29 | {110, nullptr, "StoreSaveDataThumbnail"}, | 29 | {110, nullptr, "StoreSaveDataThumbnail"}, |
| 30 | {111, nullptr, "ClearSaveDataThumbnail"}, | 30 | {111, nullptr, "ClearSaveDataThumbnail"}, |
| 31 | {120, nullptr, "CreateGuestLoginRequest"}, | 31 | {120, nullptr, "CreateGuestLoginRequest"}, |
| 32 | {130, nullptr, "LoadOpenContext"}, | 32 | {130, nullptr, "LoadOpenContext"}, // 5.0.0+ |
| 33 | {131, nullptr, "ListOpenContextStoredUsers"}, | 33 | {131, nullptr, "ListOpenContextStoredUsers"}, // 6.0.0+ |
| 34 | {140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, | 34 | {140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+ |
| 35 | {141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, | 35 | {141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ |
| 36 | {150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, | 36 | {150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, // 6.0.0+ |
| 37 | }; | 37 | }; |
| 38 | // clang-format on | 38 | // clang-format on |
| 39 | 39 | ||
diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index 9f29cdc82..f47004f84 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp | |||
| @@ -17,28 +17,29 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p | |||
| 17 | {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"}, | 17 | {3, &ACC_U1::ListOpenUsers, "ListOpenUsers"}, |
| 18 | {4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"}, | 18 | {4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"}, |
| 19 | {5, &ACC_U1::GetProfile, "GetProfile"}, | 19 | {5, &ACC_U1::GetProfile, "GetProfile"}, |
| 20 | {6, nullptr, "GetProfileDigest"}, | 20 | {6, nullptr, "GetProfileDigest"}, // 3.0.0+ |
| 21 | {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, | 21 | {50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"}, |
| 22 | {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, | 22 | {51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, |
| 23 | {60, nullptr, "ListOpenContextStoredUsers"}, | 23 | {60, nullptr, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0 |
| 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, | 24 | {99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+ |
| 25 | {100, nullptr, "GetUserRegistrationNotifier"}, | 25 | {100, nullptr, "GetUserRegistrationNotifier"}, |
| 26 | {101, nullptr, "GetUserStateChangeNotifier"}, | 26 | {101, nullptr, "GetUserStateChangeNotifier"}, |
| 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, | 27 | {102, nullptr, "GetBaasAccountManagerForSystemService"}, |
| 28 | {103, nullptr, "GetProfileUpdateNotifier"}, | 28 | {103, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, |
| 29 | {104, nullptr, "CheckNetworkServiceAvailabilityAsync"}, | 29 | {104, nullptr, "GetProfileUpdateNotifier"}, |
| 30 | {105, nullptr, "GetBaasUserAvailabilityChangeNotifier"}, | 30 | {105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+ |
| 31 | {106, nullptr, "GetProfileSyncNotifier"}, | 31 | {106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+ |
| 32 | {110, nullptr, "StoreSaveDataThumbnail"}, | 32 | {110, nullptr, "StoreSaveDataThumbnail"}, |
| 33 | {111, nullptr, "ClearSaveDataThumbnail"}, | 33 | {111, nullptr, "ClearSaveDataThumbnail"}, |
| 34 | {112, nullptr, "LoadSaveDataThumbnail"}, | 34 | {112, nullptr, "LoadSaveDataThumbnail"}, |
| 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, | 35 | {113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+ |
| 36 | {130, nullptr, "ActivateOpenContextRetention"}, | 36 | {120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+ |
| 37 | {140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"}, | 37 | {130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+ |
| 38 | {150, nullptr, "AuthenticateApplicationAsync"}, | 38 | {140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+ |
| 39 | {190, nullptr, "GetUserLastOpenedApplication"}, | 39 | {150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+ |
| 40 | {191, nullptr, "ActivateOpenContextHolder"}, | 40 | {190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0 |
| 41 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, | 41 | {191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+ |
| 42 | {997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+ | ||
| 42 | {998, nullptr, "DebugSetUserStateClose"}, | 43 | {998, nullptr, "DebugSetUserStateClose"}, |
| 43 | {999, nullptr, "DebugSetUserStateOpen"}, | 44 | {999, nullptr, "DebugSetUserStateOpen"}, |
| 44 | }; | 45 | }; |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 4df74c4f9..20f366635 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -68,6 +68,7 @@ IWindowController::IWindowController(Core::System& system_) | |||
| 68 | static const FunctionInfo functions[] = { | 68 | static const FunctionInfo functions[] = { |
| 69 | {0, nullptr, "CreateWindow"}, | 69 | {0, nullptr, "CreateWindow"}, |
| 70 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, | 70 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, |
| 71 | {2, nullptr, "GetAppletResourceUserIdOfCallerApplet"}, | ||
| 71 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, | 72 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, |
| 72 | {11, nullptr, "ReleaseForegroundRights"}, | 73 | {11, nullptr, "ReleaseForegroundRights"}, |
| 73 | {12, nullptr, "RejectToChangeIntoBackground"}, | 74 | {12, nullptr, "RejectToChangeIntoBackground"}, |
| @@ -189,8 +190,8 @@ IDisplayController::IDisplayController() : ServiceFramework("IDisplayController" | |||
| 189 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, | 190 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, |
| 190 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, | 191 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, |
| 191 | {7, nullptr, "GetCallerAppletCaptureImageEx"}, | 192 | {7, nullptr, "GetCallerAppletCaptureImageEx"}, |
| 192 | {8, nullptr, "TakeScreenShotOfOwnLayer"}, // 2.0.0+ | 193 | {8, nullptr, "TakeScreenShotOfOwnLayer"}, |
| 193 | {9, nullptr, "CopyBetweenCaptureBuffers"}, // 5.0.0+ | 194 | {9, nullptr, "CopyBetweenCaptureBuffers"}, |
| 194 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, | 195 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, |
| 195 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, | 196 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, |
| 196 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, | 197 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, |
| @@ -200,17 +201,14 @@ IDisplayController::IDisplayController() : ServiceFramework("IDisplayController" | |||
| 200 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, | 201 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, |
| 201 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, | 202 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, |
| 202 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, | 203 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, |
| 203 | // 2.0.0+ | ||
| 204 | {20, nullptr, "ClearCaptureBuffer"}, | 204 | {20, nullptr, "ClearCaptureBuffer"}, |
| 205 | {21, nullptr, "ClearAppletTransitionBuffer"}, | 205 | {21, nullptr, "ClearAppletTransitionBuffer"}, |
| 206 | // 4.0.0+ | ||
| 207 | {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, | 206 | {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, |
| 208 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, | 207 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, |
| 209 | {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"}, | 208 | {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"}, |
| 210 | {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"}, | 209 | {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"}, |
| 211 | {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"}, | 210 | {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"}, |
| 212 | {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"}, | 211 | {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"}, |
| 213 | // 6.0.0+ | ||
| 214 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, | 212 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, |
| 215 | }; | 213 | }; |
| 216 | // clang-format on | 214 | // clang-format on |
| @@ -225,7 +223,7 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} { | |||
| 225 | static const FunctionInfo functions[] = { | 223 | static const FunctionInfo functions[] = { |
| 226 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, | 224 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, |
| 227 | {1, nullptr, "OpenMainApplication"}, | 225 | {1, nullptr, "OpenMainApplication"}, |
| 228 | {10, nullptr, "EmulateButtonEvent"}, | 226 | {10, nullptr, "PerformSystemButtonPressing"}, |
| 229 | {20, nullptr, "InvalidateTransitionLayer"}, | 227 | {20, nullptr, "InvalidateTransitionLayer"}, |
| 230 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, | 228 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, |
| 231 | {40, nullptr, "GetAppletResourceUsageInfo"}, | 229 | {40, nullptr, "GetAppletResourceUsageInfo"}, |
| @@ -267,7 +265,7 @@ ISelfController::ISelfController(Core::System& system, | |||
| 267 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, | 265 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, |
| 268 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, | 266 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, |
| 269 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, | 267 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, |
| 270 | {19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"}, | 268 | {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, |
| 271 | {20, nullptr, "SetDesirableKeyboardLayout"}, | 269 | {20, nullptr, "SetDesirableKeyboardLayout"}, |
| 272 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | 270 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, |
| 273 | {41, nullptr, "IsSystemBufferSharingEnabled"}, | 271 | {41, nullptr, "IsSystemBufferSharingEnabled"}, |
| @@ -443,7 +441,7 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& | |||
| 443 | rb.Push(RESULT_SUCCESS); | 441 | rb.Push(RESULT_SUCCESS); |
| 444 | } | 442 | } |
| 445 | 443 | ||
| 446 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { | 444 | void ISelfController::SetAlbumImageOrientation(Kernel::HLERequestContext& ctx) { |
| 447 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 445 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 448 | 446 | ||
| 449 | IPC::ResponseBuilder rb{ctx, 2}; | 447 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -607,6 +605,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system, | |||
| 607 | {20, nullptr, "PushToGeneralChannel"}, | 605 | {20, nullptr, "PushToGeneralChannel"}, |
| 608 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | 606 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, |
| 609 | {31, nullptr, "GetReaderLockAccessorEx"}, | 607 | {31, nullptr, "GetReaderLockAccessorEx"}, |
| 608 | {32, nullptr, "GetWriterLockAccessorEx"}, | ||
| 610 | {40, nullptr, "GetCradleFwVersion"}, | 609 | {40, nullptr, "GetCradleFwVersion"}, |
| 611 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, | 610 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, |
| 612 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, | 611 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, |
| @@ -1132,6 +1131,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1132 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, | 1131 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, |
| 1133 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, | 1132 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, |
| 1134 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, | 1133 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, |
| 1134 | {27, nullptr, "CreateCacheStorage"}, | ||
| 1135 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, | 1135 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, |
| 1136 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, | 1136 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, |
| 1137 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, | 1137 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, |
| @@ -1157,6 +1157,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1157 | {120, nullptr, "ExecuteProgram"}, | 1157 | {120, nullptr, "ExecuteProgram"}, |
| 1158 | {121, nullptr, "ClearUserChannel"}, | 1158 | {121, nullptr, "ClearUserChannel"}, |
| 1159 | {122, nullptr, "UnpopToUserChannel"}, | 1159 | {122, nullptr, "UnpopToUserChannel"}, |
| 1160 | {123, nullptr, "GetPreviousProgramIndex"}, | ||
| 1161 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | ||
| 1160 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | 1162 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, |
| 1161 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, | 1163 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, |
| 1162 | {141, nullptr, "TryPopFromFriendInvitationStorageChannel"}, | 1164 | {141, nullptr, "TryPopFromFriendInvitationStorageChannel"}, |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 469f7f814..2f69466ec 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -138,7 +138,7 @@ private: | |||
| 138 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); | 138 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); |
| 139 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); | 139 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); |
| 140 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); | 140 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); |
| 141 | void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); | 141 | void SetAlbumImageOrientation(Kernel::HLERequestContext& ctx); |
| 142 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); | 142 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); |
| 143 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); | 143 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); |
| 144 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); | 144 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 54e63c138..fbe3686ae 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp | |||
| @@ -30,7 +30,7 @@ static Core::Frontend::SoftwareKeyboardParameters ConvertToFrontendParameters( | |||
| 30 | config.sub_text.size()); | 30 | config.sub_text.size()); |
| 31 | params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(), | 31 | params.guide_text = Common::UTF16StringFromFixedZeroTerminatedBuffer(config.guide_text.data(), |
| 32 | config.guide_text.size()); | 32 | config.guide_text.size()); |
| 33 | params.initial_text = initial_text; | 33 | params.initial_text = std::move(initial_text); |
| 34 | params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit; | 34 | params.max_length = config.length_limit == 0 ? DEFAULT_MAX_LENGTH : config.length_limit; |
| 35 | params.password = static_cast<bool>(config.is_password); | 35 | params.password = static_cast<bool>(config.is_password); |
| 36 | params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position); | 36 | params.cursor_at_beginning = static_cast<bool>(config.initial_cursor_position); |
| @@ -60,7 +60,7 @@ void SoftwareKeyboard::Initialize() { | |||
| 60 | std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); | 60 | std::memcpy(&config, keyboard_config.data(), sizeof(KeyboardConfig)); |
| 61 | 61 | ||
| 62 | const auto work_buffer_storage = broker.PopNormalDataToApplet(); | 62 | const auto work_buffer_storage = broker.PopNormalDataToApplet(); |
| 63 | ASSERT(work_buffer_storage != nullptr); | 63 | ASSERT_OR_EXECUTE(work_buffer_storage != nullptr, { return; }); |
| 64 | const auto& work_buffer = work_buffer_storage->GetData(); | 64 | const auto& work_buffer = work_buffer_storage->GetData(); |
| 65 | 65 | ||
| 66 | if (config.initial_string_size == 0) | 66 | if (config.initial_string_size == 0) |
| @@ -109,7 +109,7 @@ void SoftwareKeyboard::Execute() { | |||
| 109 | 109 | ||
| 110 | const auto parameters = ConvertToFrontendParameters(config, initial_text); | 110 | const auto parameters = ConvertToFrontendParameters(config, initial_text); |
| 111 | 111 | ||
| 112 | frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(text); }, | 112 | frontend.RequestText([this](std::optional<std::u16string> text) { WriteText(std::move(text)); }, |
| 113 | parameters); | 113 | parameters); |
| 114 | } | 114 | } |
| 115 | 115 | ||
diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp index 003ee8667..f27729ce7 100644 --- a/src/core/hle/service/am/spsm.cpp +++ b/src/core/hle/service/am/spsm.cpp | |||
| @@ -10,17 +10,17 @@ SPSM::SPSM() : ServiceFramework{"spsm"} { | |||
| 10 | // clang-format off | 10 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {0, nullptr, "GetState"}, | 12 | {0, nullptr, "GetState"}, |
| 13 | {1, nullptr, "SleepSystemAndWaitAwake"}, | 13 | {1, nullptr, "EnterSleep"}, |
| 14 | {2, nullptr, "Unknown1"}, | 14 | {2, nullptr, "GetLastWakeReason"}, |
| 15 | {3, nullptr, "Unknown2"}, | 15 | {3, nullptr, "Shutdown"}, |
| 16 | {4, nullptr, "GetNotificationMessageEventHandle"}, | 16 | {4, nullptr, "GetNotificationMessageEventHandle"}, |
| 17 | {5, nullptr, "Unknown3"}, | 17 | {5, nullptr, "ReceiveNotificationMessage"}, |
| 18 | {6, nullptr, "Unknown4"}, | 18 | {6, nullptr, "AnalyzeLogForLastSleepWakeSequence"}, |
| 19 | {7, nullptr, "Unknown5"}, | 19 | {7, nullptr, "ResetEventLog"}, |
| 20 | {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"}, | 20 | {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"}, |
| 21 | {9, nullptr, "ChangeHomeButtonLongPressingTime"}, | 21 | {9, nullptr, "ChangeHomeButtonLongPressingTime"}, |
| 22 | {10, nullptr, "Unknown6"}, | 22 | {10, nullptr, "PutErrorState"}, |
| 23 | {11, nullptr, "Unknown7"}, | 23 | {11, nullptr, "InvalidateCurrentHomeButtonPressing"}, |
| 24 | }; | 24 | }; |
| 25 | // clang-format on | 25 | // clang-format on |
| 26 | 26 | ||
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 4227a4adf..8e79f707b 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -60,6 +60,7 @@ AOC_U::AOC_U(Core::System& system) | |||
| 60 | {6, nullptr, "PrepareAddOnContentByApplicationId"}, | 60 | {6, nullptr, "PrepareAddOnContentByApplicationId"}, |
| 61 | {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, | 61 | {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, |
| 62 | {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, | 62 | {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, |
| 63 | {9, nullptr, "GetAddOnContentLostErrorCode"}, | ||
| 63 | {100, nullptr, "CreateEcPurchasedEventManager"}, | 64 | {100, nullptr, "CreateEcPurchasedEventManager"}, |
| 64 | {101, nullptr, "CreatePermanentEcPurchasedEventManager"}, | 65 | {101, nullptr, "CreatePermanentEcPurchasedEventManager"}, |
| 65 | }; | 66 | }; |
diff --git a/src/core/hle/service/bcat/bcat.cpp b/src/core/hle/service/bcat/bcat.cpp index 8bb2528c9..b31766212 100644 --- a/src/core/hle/service/bcat/bcat.cpp +++ b/src/core/hle/service/bcat/bcat.cpp | |||
| @@ -14,6 +14,8 @@ BCAT::BCAT(Core::System& system, std::shared_ptr<Module> module, | |||
| 14 | {0, &BCAT::CreateBcatService, "CreateBcatService"}, | 14 | {0, &BCAT::CreateBcatService, "CreateBcatService"}, |
| 15 | {1, &BCAT::CreateDeliveryCacheStorageService, "CreateDeliveryCacheStorageService"}, | 15 | {1, &BCAT::CreateDeliveryCacheStorageService, "CreateDeliveryCacheStorageService"}, |
| 16 | {2, &BCAT::CreateDeliveryCacheStorageServiceWithApplicationId, "CreateDeliveryCacheStorageServiceWithApplicationId"}, | 16 | {2, &BCAT::CreateDeliveryCacheStorageServiceWithApplicationId, "CreateDeliveryCacheStorageServiceWithApplicationId"}, |
| 17 | {3, nullptr, "CreateDeliveryCacheProgressService"}, | ||
| 18 | {4, nullptr, "CreateDeliveryCacheProgressServiceWithApplicationId"}, | ||
| 17 | }; | 19 | }; |
| 18 | // clang-format on | 20 | // clang-format on |
| 19 | RegisterHandlers(functions); | 21 | RegisterHandlers(functions); |
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp index 34aba7a27..603b64d4f 100644 --- a/src/core/hle/service/bcat/module.cpp +++ b/src/core/hle/service/bcat/module.cpp | |||
| @@ -143,10 +143,13 @@ public: | |||
| 143 | {20401, nullptr, "UnregisterSystemApplicationDeliveryTask"}, | 143 | {20401, nullptr, "UnregisterSystemApplicationDeliveryTask"}, |
| 144 | {20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"}, | 144 | {20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"}, |
| 145 | {30100, &IBcatService::SetPassphrase, "SetPassphrase"}, | 145 | {30100, &IBcatService::SetPassphrase, "SetPassphrase"}, |
| 146 | {30101, nullptr, "Unknown"}, | ||
| 147 | {30102, nullptr, "Unknown2"}, | ||
| 146 | {30200, nullptr, "RegisterBackgroundDeliveryTask"}, | 148 | {30200, nullptr, "RegisterBackgroundDeliveryTask"}, |
| 147 | {30201, nullptr, "UnregisterBackgroundDeliveryTask"}, | 149 | {30201, nullptr, "UnregisterBackgroundDeliveryTask"}, |
| 148 | {30202, nullptr, "BlockDeliveryTask"}, | 150 | {30202, nullptr, "BlockDeliveryTask"}, |
| 149 | {30203, nullptr, "UnblockDeliveryTask"}, | 151 | {30203, nullptr, "UnblockDeliveryTask"}, |
| 152 | {30210, nullptr, "SetDeliveryTaskTimer"}, | ||
| 150 | {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, | 153 | {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, |
| 151 | {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, | 154 | {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, |
| 152 | {90200, nullptr, "GetDeliveryList"}, | 155 | {90200, nullptr, "GetDeliveryList"}, |
diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp index 1c1ecdb60..fac6b2f9c 100644 --- a/src/core/hle/service/bpc/bpc.cpp +++ b/src/core/hle/service/bpc/bpc.cpp | |||
| @@ -23,9 +23,14 @@ public: | |||
| 23 | {5, nullptr, "GetBoardPowerControlEvent"}, | 23 | {5, nullptr, "GetBoardPowerControlEvent"}, |
| 24 | {6, nullptr, "GetSleepButtonState"}, | 24 | {6, nullptr, "GetSleepButtonState"}, |
| 25 | {7, nullptr, "GetPowerEvent"}, | 25 | {7, nullptr, "GetPowerEvent"}, |
| 26 | {8, nullptr, "Unknown1"}, | 26 | {8, nullptr, "CreateWakeupTimer"}, |
| 27 | {9, nullptr, "Unknown2"}, | 27 | {9, nullptr, "CancelWakeupTimer"}, |
| 28 | {10, nullptr, "Unknown3"}, | 28 | {10, nullptr, "EnableWakeupTimerOnDevice"}, |
| 29 | {11, nullptr, "CreateWakeupTimerEx"}, | ||
| 30 | {12, nullptr, "GetLastEnabledWakeupTimerType"}, | ||
| 31 | {13, nullptr, "CleanAllWakeupTimers"}, | ||
| 32 | {14, nullptr, "Unknown"}, | ||
| 33 | {15, nullptr, "Unknown2"}, | ||
| 29 | }; | 34 | }; |
| 30 | // clang-format on | 35 | // clang-format on |
| 31 | 36 | ||
| @@ -38,10 +43,11 @@ public: | |||
| 38 | explicit BPC_R() : ServiceFramework{"bpc:r"} { | 43 | explicit BPC_R() : ServiceFramework{"bpc:r"} { |
| 39 | // clang-format off | 44 | // clang-format off |
| 40 | static const FunctionInfo functions[] = { | 45 | static const FunctionInfo functions[] = { |
| 41 | {0, nullptr, "GetExternalRtcValue"}, | 46 | {0, nullptr, "GetRtcTime"}, |
| 42 | {1, nullptr, "SetExternalRtcValue"}, | 47 | {1, nullptr, "SetRtcTime"}, |
| 43 | {2, nullptr, "ReadExternalRtcResetFlag"}, | 48 | {2, nullptr, "GetRtcResetDetected"}, |
| 44 | {3, nullptr, "ClearExternalRtcResetFlag"}, | 49 | {3, nullptr, "ClearRtcResetDetected"}, |
| 50 | {4, nullptr, "SetUpRtcResetOnShutdown"}, | ||
| 45 | }; | 51 | }; |
| 46 | // clang-format on | 52 | // clang-format on |
| 47 | 53 | ||
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index 40a06c9fd..f311afa2f 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp | |||
| @@ -58,102 +58,103 @@ public: | |||
| 58 | {1, nullptr, "InitializeBluetooth"}, | 58 | {1, nullptr, "InitializeBluetooth"}, |
| 59 | {2, nullptr, "EnableBluetooth"}, | 59 | {2, nullptr, "EnableBluetooth"}, |
| 60 | {3, nullptr, "DisableBluetooth"}, | 60 | {3, nullptr, "DisableBluetooth"}, |
| 61 | {4, nullptr, "CleanupBluetooth"}, | 61 | {4, nullptr, "FinalizeBluetooth"}, |
| 62 | {5, nullptr, "GetAdapterProperties"}, | 62 | {5, nullptr, "GetAdapterProperties"}, |
| 63 | {6, nullptr, "GetAdapterProperty"}, | 63 | {6, nullptr, "GetAdapterProperty"}, |
| 64 | {7, nullptr, "SetAdapterProperty"}, | 64 | {7, nullptr, "SetAdapterProperty"}, |
| 65 | {8, nullptr, "StartDiscovery"}, | 65 | {8, nullptr, "StartInquiry"}, |
| 66 | {9, nullptr, "CancelDiscovery"}, | 66 | {9, nullptr, "StopInquiry"}, |
| 67 | {10, nullptr, "CreateBond"}, | 67 | {10, nullptr, "CreateBond"}, |
| 68 | {11, nullptr, "RemoveBond"}, | 68 | {11, nullptr, "RemoveBond"}, |
| 69 | {12, nullptr, "CancelBond"}, | 69 | {12, nullptr, "CancelBond"}, |
| 70 | {13, nullptr, "PinReply"}, | 70 | {13, nullptr, "RespondToPinRequest"}, |
| 71 | {14, nullptr, "SspReply"}, | 71 | {14, nullptr, "RespondToSspRequest"}, |
| 72 | {15, nullptr, "GetEventInfo"}, | 72 | {15, nullptr, "GetEventInfo"}, |
| 73 | {16, nullptr, "InitializeHid"}, | 73 | {16, nullptr, "InitializeHid"}, |
| 74 | {17, nullptr, "HidConnect"}, | 74 | {17, nullptr, "OpenHidConnection"}, |
| 75 | {18, nullptr, "HidDisconnect"}, | 75 | {18, nullptr, "CloseHidConnection"}, |
| 76 | {19, nullptr, "HidSendData"}, | 76 | {19, nullptr, "WriteHidData"}, |
| 77 | {20, nullptr, "HidSendData2"}, | 77 | {20, nullptr, "WriteHidData2"}, |
| 78 | {21, nullptr, "HidSetReport"}, | 78 | {21, nullptr, "SetHidReport"}, |
| 79 | {22, nullptr, "HidGetReport"}, | 79 | {22, nullptr, "GetHidReport"}, |
| 80 | {23, nullptr, "HidWakeController"}, | 80 | {23, nullptr, "TriggerConnection"}, |
| 81 | {24, nullptr, "HidAddPairedDevice"}, | 81 | {24, nullptr, "AddPairedDeviceInfo"}, |
| 82 | {25, nullptr, "HidGetPairedDevice"}, | 82 | {25, nullptr, "GetPairedDeviceInfo"}, |
| 83 | {26, nullptr, "CleanupHid"}, | 83 | {26, nullptr, "FinalizeHid"}, |
| 84 | {27, nullptr, "HidGetEventInfo"}, | 84 | {27, nullptr, "GetHidEventInfo"}, |
| 85 | {28, nullptr, "ExtSetTsi"}, | 85 | {28, nullptr, "SetTsi"}, |
| 86 | {29, nullptr, "ExtSetBurstMode"}, | 86 | {29, nullptr, "EnableBurstMode"}, |
| 87 | {30, nullptr, "ExtSetZeroRetran"}, | 87 | {30, nullptr, "SetZeroRetransmission"}, |
| 88 | {31, nullptr, "ExtSetMcMode"}, | 88 | {31, nullptr, "EnableMcMode"}, |
| 89 | {32, nullptr, "ExtStartLlrMode"}, | 89 | {32, nullptr, "EnableLlrScan"}, |
| 90 | {33, nullptr, "ExtExitLlrMode"}, | 90 | {33, nullptr, "DisableLlrScan"}, |
| 91 | {34, nullptr, "ExtSetRadio"}, | 91 | {34, nullptr, "EnableRadio"}, |
| 92 | {35, nullptr, "ExtSetVisibility"}, | 92 | {35, nullptr, "SetVisibility"}, |
| 93 | {36, nullptr, "ExtSetTbfcScan"}, | 93 | {36, nullptr, "EnableTbfcScan"}, |
| 94 | {37, nullptr, "RegisterHidReportEvent"}, | 94 | {37, nullptr, "RegisterHidReportEvent"}, |
| 95 | {38, nullptr, "HidGetReportEventInfo"}, | 95 | {38, nullptr, "GetHidReportEventInfo"}, |
| 96 | {39, nullptr, "GetLatestPlr"}, | 96 | {39, nullptr, "GetLatestPlr"}, |
| 97 | {40, nullptr, "ExtGetPendingConnections"}, | 97 | {40, nullptr, "GetPendingConnections"}, |
| 98 | {41, nullptr, "GetChannelMap"}, | 98 | {41, nullptr, "GetChannelMap"}, |
| 99 | {42, nullptr, "EnableBluetoothBoostSetting"}, | 99 | {42, nullptr, "EnableTxPowerBoostSetting"}, |
| 100 | {43, nullptr, "IsBluetoothBoostSettingEnabled"}, | 100 | {43, nullptr, "IsTxPowerBoostSettingEnabled"}, |
| 101 | {44, nullptr, "EnableBluetoothAfhSetting"}, | 101 | {44, nullptr, "EnableAfhSetting"}, |
| 102 | {45, nullptr, "IsBluetoothAfhSettingEnabled"}, | 102 | {45, nullptr, "IsAfhSettingEnabled"}, |
| 103 | {46, nullptr, "InitializeBluetoothLe"}, | 103 | {46, nullptr, "InitializeBle"}, |
| 104 | {47, nullptr, "EnableBluetoothLe"}, | 104 | {47, nullptr, "EnableBle"}, |
| 105 | {48, nullptr, "DisableBluetoothLe"}, | 105 | {48, nullptr, "DisableBle"}, |
| 106 | {49, nullptr, "CleanupBluetoothLe"}, | 106 | {49, nullptr, "FinalizeBle"}, |
| 107 | {50, nullptr, "SetLeVisibility"}, | 107 | {50, nullptr, "SetBleVisibility"}, |
| 108 | {51, nullptr, "SetLeConnectionParameter"}, | 108 | {51, nullptr, "SetBleConnectionParameter"}, |
| 109 | {52, nullptr, "SetLeDefaultConnectionParameter"}, | 109 | {52, nullptr, "SetBleDefaultConnectionParameter"}, |
| 110 | {53, nullptr, "SetLeAdvertiseData"}, | 110 | {53, nullptr, "SetBleAdvertiseData"}, |
| 111 | {54, nullptr, "SetLeAdvertiseParameter"}, | 111 | {54, nullptr, "SetBleAdvertiseParameter"}, |
| 112 | {55, nullptr, "StartLeScan"}, | 112 | {55, nullptr, "StartBleScan"}, |
| 113 | {56, nullptr, "StopLeScan"}, | 113 | {56, nullptr, "StopBleScan"}, |
| 114 | {57, nullptr, "AddLeScanFilterCondition"}, | 114 | {57, nullptr, "AddBleScanFilterCondition"}, |
| 115 | {58, nullptr, "DeleteLeScanFilterCondition"}, | 115 | {58, nullptr, "DeleteBleScanFilterCondition"}, |
| 116 | {59, nullptr, "DeleteLeScanFilter"}, | 116 | {59, nullptr, "DeleteBleScanFilter"}, |
| 117 | {60, nullptr, "ClearLeScanFilters"}, | 117 | {60, nullptr, "ClearBleScanFilters"}, |
| 118 | {61, nullptr, "EnableLeScanFilter"}, | 118 | {61, nullptr, "EnableBleScanFilter"}, |
| 119 | {62, nullptr, "RegisterLeClient"}, | 119 | {62, nullptr, "RegisterGattClient"}, |
| 120 | {63, nullptr, "UnregisterLeClient"}, | 120 | {63, nullptr, "UnregisterGattClient"}, |
| 121 | {64, nullptr, "UnregisterLeClientAll"}, | 121 | {64, nullptr, "UnregisterAllGattClients"}, |
| 122 | {65, nullptr, "LeClientConnect"}, | 122 | {65, nullptr, "ConnectGattServer"}, |
| 123 | {66, nullptr, "LeClientCancelConnection"}, | 123 | {66, nullptr, "CancelConnectGattServer"}, |
| 124 | {67, nullptr, "LeClientDisconnect"}, | 124 | {67, nullptr, "DisconnectGattServer"}, |
| 125 | {68, nullptr, "LeClientGetAttributes"}, | 125 | {68, nullptr, "GetGattAttribute"}, |
| 126 | {69, nullptr, "LeClientDiscoverService"}, | 126 | {69, nullptr, "GetGattService"}, |
| 127 | {70, nullptr, "LeClientConfigureMtu"}, | 127 | {70, nullptr, "ConfigureAttMtu"}, |
| 128 | {71, nullptr, "RegisterLeServer"}, | 128 | {71, nullptr, "RegisterGattServer"}, |
| 129 | {72, nullptr, "UnregisterLeServer"}, | 129 | {72, nullptr, "UnregisterGattServer"}, |
| 130 | {73, nullptr, "LeServerConnect"}, | 130 | {73, nullptr, "ConnectGattClient"}, |
| 131 | {74, nullptr, "LeServerDisconnect"}, | 131 | {74, nullptr, "DisconnectGattClient"}, |
| 132 | {75, nullptr, "CreateLeService"}, | 132 | {75, nullptr, "AddGattService"}, |
| 133 | {76, nullptr, "StartLeService"}, | 133 | {76, nullptr, "EnableGattService"}, |
| 134 | {77, nullptr, "AddLeCharacteristic"}, | 134 | {77, nullptr, "AddGattCharacteristic"}, |
| 135 | {78, nullptr, "AddLeDescriptor"}, | 135 | {78, nullptr, "AddGattDescriptor"}, |
| 136 | {79, nullptr, "GetLeCoreEventInfo"}, | 136 | {79, nullptr, "GetBleManagedEventInfo"}, |
| 137 | {80, nullptr, "LeGetFirstCharacteristic"}, | 137 | {80, nullptr, "GetGattFirstCharacteristic"}, |
| 138 | {81, nullptr, "LeGetNextCharacteristic"}, | 138 | {81, nullptr, "GetGattNextCharacteristic"}, |
| 139 | {82, nullptr, "LeGetFirstDescriptor"}, | 139 | {82, nullptr, "GetGattFirstDescriptor"}, |
| 140 | {83, nullptr, "LeGetNextDescriptor"}, | 140 | {83, nullptr, "GetGattNextDescriptor"}, |
| 141 | {84, nullptr, "RegisterLeCoreDataPath"}, | 141 | {84, nullptr, "RegisterGattManagedDataPath"}, |
| 142 | {85, nullptr, "UnregisterLeCoreDataPath"}, | 142 | {85, nullptr, "UnregisterGattManagedDataPath"}, |
| 143 | {86, nullptr, "RegisterLeHidDataPath"}, | 143 | {86, nullptr, "RegisterGattHidDataPath"}, |
| 144 | {87, nullptr, "UnregisterLeHidDataPath"}, | 144 | {87, nullptr, "UnregisterGattHidDataPath"}, |
| 145 | {88, nullptr, "RegisterLeDataPath"}, | 145 | {88, nullptr, "RegisterGattDataPath"}, |
| 146 | {89, nullptr, "UnregisterLeDataPath"}, | 146 | {89, nullptr, "UnregisterGattDataPath"}, |
| 147 | {90, nullptr, "LeClientReadCharacteristic"}, | 147 | {90, nullptr, "ReadGattCharacteristic"}, |
| 148 | {91, nullptr, "LeClientReadDescriptor"}, | 148 | {91, nullptr, "ReadGattDescriptor"}, |
| 149 | {92, nullptr, "LeClientWriteCharacteristic"}, | 149 | {92, nullptr, "WriteGattCharacteristic"}, |
| 150 | {93, nullptr, "LeClientWriteDescriptor"}, | 150 | {93, nullptr, "WriteGattDescriptor"}, |
| 151 | {94, nullptr, "LeClientRegisterNotification"}, | 151 | {94, nullptr, "RegisterGattNotification"}, |
| 152 | {95, nullptr, "LeClientDeregisterNotification"}, | 152 | {95, nullptr, "UnregisterGattNotification"}, |
| 153 | {96, nullptr, "GetLeHidEventInfo"}, | 153 | {96, nullptr, "GetLeHidEventInfo"}, |
| 154 | {97, nullptr, "RegisterBleHidEvent"}, | 154 | {97, nullptr, "RegisterBleHidEvent"}, |
| 155 | {98, nullptr, "SetLeScanParameter"}, | 155 | {98, nullptr, "SetBleScanParameter"}, |
| 156 | {256, nullptr, "GetIsManufacturingMode"}, | 156 | {99, nullptr, "MoveToSecondaryPiconet"}, |
| 157 | {256, nullptr, "IsManufacturingMode"}, | ||
| 157 | {257, nullptr, "EmulateBluetoothCrash"}, | 158 | {257, nullptr, "EmulateBluetoothCrash"}, |
| 158 | {258, nullptr, "GetBleChannelMap"}, | 159 | {258, nullptr, "GetBleChannelMap"}, |
| 159 | }; | 160 | }; |
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 251b3c9df..0d251c6d0 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp | |||
| @@ -132,66 +132,71 @@ public: | |||
| 132 | explicit BTM() : ServiceFramework{"btm"} { | 132 | explicit BTM() : ServiceFramework{"btm"} { |
| 133 | // clang-format off | 133 | // clang-format off |
| 134 | static const FunctionInfo functions[] = { | 134 | static const FunctionInfo functions[] = { |
| 135 | {0, nullptr, "Unknown1"}, | 135 | {0, nullptr, "GetState"}, |
| 136 | {1, nullptr, "Unknown2"}, | 136 | {1, nullptr, "GetHostDeviceProperty"}, |
| 137 | {2, nullptr, "RegisterSystemEventForConnectedDeviceCondition"}, | 137 | {2, nullptr, "AcquireDeviceConditionEvent"}, |
| 138 | {3, nullptr, "Unknown3"}, | 138 | {3, nullptr, "GetDeviceCondition"}, |
| 139 | {4, nullptr, "Unknown4"}, | 139 | {4, nullptr, "SetBurstMode"}, |
| 140 | {5, nullptr, "Unknown5"}, | 140 | {5, nullptr, "SetSlotMode"}, |
| 141 | {6, nullptr, "Unknown6"}, | 141 | {6, nullptr, "SetBluetoothMode"}, |
| 142 | {7, nullptr, "Unknown7"}, | 142 | {7, nullptr, "SetWlanMode"}, |
| 143 | {8, nullptr, "RegisterSystemEventForRegisteredDeviceInfo"}, | 143 | {8, nullptr, "AcquireDeviceInfoEvent"}, |
| 144 | {9, nullptr, "Unknown8"}, | 144 | {9, nullptr, "GetDeviceInfo"}, |
| 145 | {10, nullptr, "Unknown9"}, | 145 | {10, nullptr, "AddDeviceInfo"}, |
| 146 | {11, nullptr, "Unknown10"}, | 146 | {11, nullptr, "RemoveDeviceInfo"}, |
| 147 | {12, nullptr, "Unknown11"}, | 147 | {12, nullptr, "IncreaseDeviceInfoOrder"}, |
| 148 | {13, nullptr, "Unknown12"}, | 148 | {13, nullptr, "LlrNotify"}, |
| 149 | {14, nullptr, "EnableRadio"}, | 149 | {14, nullptr, "EnableRadio"}, |
| 150 | {15, nullptr, "DisableRadio"}, | 150 | {15, nullptr, "DisableRadio"}, |
| 151 | {16, nullptr, "Unknown13"}, | 151 | {16, nullptr, "HidDisconnect"}, |
| 152 | {17, nullptr, "Unknown14"}, | 152 | {17, nullptr, "HidSetRetransmissionMode"}, |
| 153 | {18, nullptr, "Unknown15"}, | 153 | {18, nullptr, "AcquireAwakeReqEvent"}, |
| 154 | {19, nullptr, "Unknown16"}, | 154 | {19, nullptr, "AcquireLlrStateEvent"}, |
| 155 | {20, nullptr, "Unknown17"}, | 155 | {20, nullptr, "IsLlrStarted"}, |
| 156 | {21, nullptr, "Unknown18"}, | 156 | {21, nullptr, "EnableSlotSaving"}, |
| 157 | {22, nullptr, "Unknown19"}, | 157 | {22, nullptr, "ProtectDeviceInfo"}, |
| 158 | {23, nullptr, "Unknown20"}, | 158 | {23, nullptr, "AcquireBleScanEvent"}, |
| 159 | {24, nullptr, "Unknown21"}, | 159 | {24, nullptr, "GetBleScanParameterGeneral"}, |
| 160 | {25, nullptr, "Unknown22"}, | 160 | {25, nullptr, "GetBleScanParameterSmartDevice"}, |
| 161 | {26, nullptr, "Unknown23"}, | 161 | {26, nullptr, "StartBleScanForGeneral"}, |
| 162 | {27, nullptr, "Unknown24"}, | 162 | {27, nullptr, "StopBleScanForGeneral"}, |
| 163 | {28, nullptr, "Unknown25"}, | 163 | {28, nullptr, "GetBleScanResultsForGeneral"}, |
| 164 | {29, nullptr, "Unknown26"}, | 164 | {29, nullptr, "StartBleScanForPairedDevice"}, |
| 165 | {30, nullptr, "Unknown27"}, | 165 | {30, nullptr, "StopBleScanForPairedDevice"}, |
| 166 | {31, nullptr, "Unknown28"}, | 166 | {31, nullptr, "StartBleScanForSmartDevice"}, |
| 167 | {32, nullptr, "Unknown29"}, | 167 | {32, nullptr, "StopBleScanForSmartDevice"}, |
| 168 | {33, nullptr, "Unknown30"}, | 168 | {33, nullptr, "GetBleScanResultsForSmartDevice"}, |
| 169 | {34, nullptr, "Unknown31"}, | 169 | {34, nullptr, "AcquireBleConnectionEvent"}, |
| 170 | {35, nullptr, "Unknown32"}, | 170 | {35, nullptr, "BleConnect"}, |
| 171 | {36, nullptr, "Unknown33"}, | 171 | {36, nullptr, "BleOverrideConnection"}, |
| 172 | {37, nullptr, "Unknown34"}, | 172 | {37, nullptr, "BleDisconnect"}, |
| 173 | {38, nullptr, "Unknown35"}, | 173 | {38, nullptr, "BleGetConnectionState"}, |
| 174 | {39, nullptr, "Unknown36"}, | 174 | {39, nullptr, "BleGetGattClientConditionList"}, |
| 175 | {40, nullptr, "Unknown37"}, | 175 | {40, nullptr, "AcquireBlePairingEvent"}, |
| 176 | {41, nullptr, "Unknown38"}, | 176 | {41, nullptr, "BlePairDevice"}, |
| 177 | {42, nullptr, "Unknown39"}, | 177 | {42, nullptr, "BleUnpairDeviceOnBoth"}, |
| 178 | {43, nullptr, "Unknown40"}, | 178 | {43, nullptr, "BleUnpairDevice"}, |
| 179 | {44, nullptr, "Unknown41"}, | 179 | {44, nullptr, "BleGetPairedAddresses"}, |
| 180 | {45, nullptr, "Unknown42"}, | 180 | {45, nullptr, "AcquireBleServiceDiscoveryEvent"}, |
| 181 | {46, nullptr, "Unknown43"}, | 181 | {46, nullptr, "GetGattServices"}, |
| 182 | {47, nullptr, "Unknown44"}, | 182 | {47, nullptr, "GetGattService"}, |
| 183 | {48, nullptr, "Unknown45"}, | 183 | {48, nullptr, "GetGattIncludedServices"}, |
| 184 | {49, nullptr, "Unknown46"}, | 184 | {49, nullptr, "GetBelongingService"}, |
| 185 | {50, nullptr, "Unknown47"}, | 185 | {50, nullptr, "GetGattCharacteristics"}, |
| 186 | {51, nullptr, "Unknown48"}, | 186 | {51, nullptr, "GetGattDescriptors"}, |
| 187 | {52, nullptr, "Unknown49"}, | 187 | {52, nullptr, "AcquireBleMtuConfigEvent"}, |
| 188 | {53, nullptr, "Unknown50"}, | 188 | {53, nullptr, "ConfigureBleMtu"}, |
| 189 | {54, nullptr, "Unknown51"}, | 189 | {54, nullptr, "GetBleMtu"}, |
| 190 | {55, nullptr, "Unknown52"}, | 190 | {55, nullptr, "RegisterBleGattDataPath"}, |
| 191 | {56, nullptr, "Unknown53"}, | 191 | {56, nullptr, "UnregisterBleGattDataPath"}, |
| 192 | {57, nullptr, "Unknown54"}, | 192 | {57, nullptr, "RegisterAppletResourceUserId"}, |
| 193 | {58, nullptr, "Unknown55"}, | 193 | {58, nullptr, "UnregisterAppletResourceUserId"}, |
| 194 | {59, nullptr, "Unknown56"}, | 194 | {59, nullptr, "SetAppletResourceUserId"}, |
| 195 | {60, nullptr, "Unknown60"}, | ||
| 196 | {61, nullptr, "Unknown61"}, | ||
| 197 | {62, nullptr, "Unknown62"}, | ||
| 198 | {63, nullptr, "Unknown63"}, | ||
| 199 | {64, nullptr, "Unknown64"}, | ||
| 195 | }; | 200 | }; |
| 196 | // clang-format on | 201 | // clang-format on |
| 197 | 202 | ||
| @@ -204,19 +209,19 @@ public: | |||
| 204 | explicit BTM_DBG() : ServiceFramework{"btm:dbg"} { | 209 | explicit BTM_DBG() : ServiceFramework{"btm:dbg"} { |
| 205 | // clang-format off | 210 | // clang-format off |
| 206 | static const FunctionInfo functions[] = { | 211 | static const FunctionInfo functions[] = { |
| 207 | {0, nullptr, "RegisterSystemEventForDiscovery"}, | 212 | {0, nullptr, "AcquireDiscoveryEvent"}, |
| 208 | {1, nullptr, "Unknown1"}, | 213 | {1, nullptr, "StartDiscovery"}, |
| 209 | {2, nullptr, "Unknown2"}, | 214 | {2, nullptr, "CancelDiscovery"}, |
| 210 | {3, nullptr, "Unknown3"}, | 215 | {3, nullptr, "GetDeviceProperty"}, |
| 211 | {4, nullptr, "Unknown4"}, | 216 | {4, nullptr, "CreateBond"}, |
| 212 | {5, nullptr, "Unknown5"}, | 217 | {5, nullptr, "CancelBond"}, |
| 213 | {6, nullptr, "Unknown6"}, | 218 | {6, nullptr, "SetTsiMode"}, |
| 214 | {7, nullptr, "Unknown7"}, | 219 | {7, nullptr, "GeneralTest"}, |
| 215 | {8, nullptr, "Unknown8"}, | 220 | {8, nullptr, "HidConnect"}, |
| 216 | {9, nullptr, "Unknown9"}, | 221 | {9, nullptr, "GeneralGet"}, |
| 217 | {10, nullptr, "Unknown10"}, | 222 | {10, nullptr, "GetGattClientDisconnectionReason"}, |
| 218 | {11, nullptr, "Unknown11"}, | 223 | {11, nullptr, "GetBleConnectionParameter"}, |
| 219 | {12, nullptr, "Unknown11"}, | 224 | {12, nullptr, "GetBleConnectionParameterRequest"}, |
| 220 | }; | 225 | }; |
| 221 | // clang-format on | 226 | // clang-format on |
| 222 | 227 | ||
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp index 26c8a7081..ba5749b84 100644 --- a/src/core/hle/service/caps/caps.cpp +++ b/src/core/hle/service/caps/caps.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2018 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h index fc70a4c27..b8c67b6e2 100644 --- a/src/core/hle/service/caps/caps.h +++ b/src/core/hle/service/caps/caps.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2018 yuzu emulator team | 1 | // Copyright 2018 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -12,73 +12,79 @@ class ServiceManager; | |||
| 12 | 12 | ||
| 13 | namespace Service::Capture { | 13 | namespace Service::Capture { |
| 14 | 14 | ||
| 15 | enum AlbumImageOrientation { | 15 | enum class AlbumImageOrientation { |
| 16 | Orientation0 = 0, | 16 | Orientation0 = 0, |
| 17 | Orientation1 = 1, | 17 | Orientation1 = 1, |
| 18 | Orientation2 = 2, | 18 | Orientation2 = 2, |
| 19 | Orientation3 = 3, | 19 | Orientation3 = 3, |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | enum AlbumReportOption { | 22 | enum class AlbumReportOption { |
| 23 | Disable = 0, | 23 | Disable = 0, |
| 24 | Enable = 1, | 24 | Enable = 1, |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | enum ContentType : u8 { | 27 | enum class ContentType : u8 { |
| 28 | Screenshot = 0, | 28 | Screenshot = 0, |
| 29 | Movie = 1, | 29 | Movie = 1, |
| 30 | ExtraMovie = 3, | 30 | ExtraMovie = 3, |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | enum AlbumStorage : u8 { | 33 | enum class AlbumStorage : u8 { |
| 34 | NAND = 0, | 34 | NAND = 0, |
| 35 | SD = 1, | 35 | SD = 1, |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | struct AlbumFileDateTime { | 38 | struct AlbumFileDateTime { |
| 39 | u16 year; | 39 | s16 year{}; |
| 40 | u8 month; | 40 | s8 month{}; |
| 41 | u8 day; | 41 | s8 day{}; |
| 42 | u8 hour; | 42 | s8 hour{}; |
| 43 | u8 minute; | 43 | s8 minute{}; |
| 44 | u8 second; | 44 | s8 second{}; |
| 45 | u8 uid; | 45 | s8 uid{}; |
| 46 | }; | 46 | }; |
| 47 | static_assert(sizeof(AlbumFileDateTime) == 0x8, "AlbumFileDateTime has incorrect size."); | ||
| 47 | 48 | ||
| 48 | struct AlbumEntry { | 49 | struct AlbumEntry { |
| 49 | u64 size; | 50 | u64 size{}; |
| 50 | u64 application_id; | 51 | u64 application_id{}; |
| 51 | AlbumFileDateTime datetime; | 52 | AlbumFileDateTime datetime{}; |
| 52 | AlbumStorage storage; | 53 | AlbumStorage storage{}; |
| 53 | ContentType content; | 54 | ContentType content{}; |
| 54 | u8 padding[6]; | 55 | INSERT_PADDING_BYTES(6); |
| 55 | }; | 56 | }; |
| 57 | static_assert(sizeof(AlbumEntry) == 0x20, "AlbumEntry has incorrect size."); | ||
| 56 | 58 | ||
| 57 | struct AlbumFileEntry { | 59 | struct AlbumFileEntry { |
| 58 | u64 size; | 60 | u64 size{}; // Size of the entry |
| 59 | u64 hash; | 61 | u64 hash{}; // AES256 with hardcoded key over AlbumEntry |
| 60 | AlbumFileDateTime datetime; | 62 | AlbumFileDateTime datetime{}; |
| 61 | AlbumStorage storage; | 63 | AlbumStorage storage{}; |
| 62 | ContentType content; | 64 | ContentType content{}; |
| 63 | u8 padding[5]; | 65 | INSERT_PADDING_BYTES(5); |
| 64 | u8 unknown; | 66 | u8 unknown{1}; // Set to 1 on official SW |
| 65 | }; | 67 | }; |
| 68 | static_assert(sizeof(AlbumFileEntry) == 0x20, "AlbumFileEntry has incorrect size."); | ||
| 66 | 69 | ||
| 67 | struct ApplicationAlbumEntry { | 70 | struct ApplicationAlbumEntry { |
| 68 | u64 size; | 71 | u64 size{}; // Size of the entry |
| 69 | u64 hash; | 72 | u64 hash{}; // AES256 with hardcoded key over AlbumEntry |
| 70 | AlbumFileDateTime datetime; | 73 | AlbumFileDateTime datetime{}; |
| 71 | AlbumStorage storage; | 74 | AlbumStorage storage{}; |
| 72 | ContentType content; | 75 | ContentType content{}; |
| 73 | u8 padding[5]; | 76 | INSERT_PADDING_BYTES(5); |
| 74 | u8 unknown; | 77 | u8 unknown{1}; // Set to 1 on official SW |
| 75 | }; | 78 | }; |
| 79 | static_assert(sizeof(ApplicationAlbumEntry) == 0x20, "ApplicationAlbumEntry has incorrect size."); | ||
| 76 | 80 | ||
| 77 | struct ApplicationAlbumFileEntry { | 81 | struct ApplicationAlbumFileEntry { |
| 78 | ApplicationAlbumEntry entry; | 82 | ApplicationAlbumEntry entry{}; |
| 79 | AlbumFileDateTime datetime; | 83 | AlbumFileDateTime datetime{}; |
| 80 | u64 unknown; | 84 | u64 unknown{}; |
| 81 | }; | 85 | }; |
| 86 | static_assert(sizeof(ApplicationAlbumFileEntry) == 0x30, | ||
| 87 | "ApplicationAlbumFileEntry has incorrect size."); | ||
| 82 | 88 | ||
| 83 | /// Registers all Capture services with the specified service manager. | 89 | /// Registers all Capture services with the specified service manager. |
| 84 | void InstallInterfaces(SM::ServiceManager& sm); | 90 | void InstallInterfaces(SM::ServiceManager& sm); |
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp index 88a3fdc05..a0a3b2ae3 100644 --- a/src/core/hle/service/caps/caps_a.cpp +++ b/src/core/hle/service/caps/caps_a.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h index 8de832491..cb93aad5b 100644 --- a/src/core/hle/service/caps/caps_a.h +++ b/src/core/hle/service/caps/caps_a.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_c.cpp b/src/core/hle/service/caps/caps_c.cpp index ea6452ffa..ab17a187e 100644 --- a/src/core/hle/service/caps/caps_c.cpp +++ b/src/core/hle/service/caps/caps_c.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_c.h b/src/core/hle/service/caps/caps_c.h index d07cdb441..a9d028689 100644 --- a/src/core/hle/service/caps/caps_c.h +++ b/src/core/hle/service/caps/caps_c.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_sc.cpp b/src/core/hle/service/caps/caps_sc.cpp index d01a8a58e..822ee96c8 100644 --- a/src/core/hle/service/caps/caps_sc.cpp +++ b/src/core/hle/service/caps/caps_sc.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_sc.h b/src/core/hle/service/caps/caps_sc.h index 9ba372f7a..ac3e929ca 100644 --- a/src/core/hle/service/caps/caps_sc.h +++ b/src/core/hle/service/caps/caps_sc.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp index eaa3a7494..24dc716e7 100644 --- a/src/core/hle/service/caps/caps_ss.cpp +++ b/src/core/hle/service/caps/caps_ss.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_ss.h b/src/core/hle/service/caps/caps_ss.h index e258a6925..450686e4f 100644 --- a/src/core/hle/service/caps/caps_ss.h +++ b/src/core/hle/service/caps/caps_ss.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp index e8b0698e8..fffb2ecf9 100644 --- a/src/core/hle/service/caps/caps_su.cpp +++ b/src/core/hle/service/caps/caps_su.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h index c494d7c84..62c9603a9 100644 --- a/src/core/hle/service/caps/caps_su.h +++ b/src/core/hle/service/caps/caps_su.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp index 78bab6ed8..f36d8de2d 100644 --- a/src/core/hle/service/caps/caps_u.cpp +++ b/src/core/hle/service/caps/caps_u.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| @@ -58,19 +58,25 @@ void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& c | |||
| 58 | // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total | 58 | // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total |
| 59 | // output entries (which is copied to a s32 by official SW). | 59 | // output entries (which is copied to a s32 by official SW). |
| 60 | IPC::RequestParser rp{ctx}; | 60 | IPC::RequestParser rp{ctx}; |
| 61 | [[maybe_unused]] const auto application_album_file_entries = rp.PopRaw<std::array<u8, 0x30>>(); | 61 | const auto pid{rp.Pop<s32>()}; |
| 62 | const auto pid = rp.Pop<s32>(); | 62 | const auto content_type{rp.PopEnum<ContentType>()}; |
| 63 | const auto content_type = rp.PopRaw<ContentType>(); | 63 | const auto start_posix_time{rp.Pop<s64>()}; |
| 64 | [[maybe_unused]] const auto start_datetime = rp.PopRaw<AlbumFileDateTime>(); | 64 | const auto end_posix_time{rp.Pop<s64>()}; |
| 65 | [[maybe_unused]] const auto end_datetime = rp.PopRaw<AlbumFileDateTime>(); | 65 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 66 | const auto applet_resource_user_id = rp.Pop<u64>(); | 66 | |
| 67 | // TODO: Update this when we implement the album. | ||
| 68 | // Currently we do not have a method of accessing album entries, set this to 0 for now. | ||
| 69 | constexpr s32 total_entries{0}; | ||
| 70 | |||
| 67 | LOG_WARNING(Service_Capture, | 71 | LOG_WARNING(Service_Capture, |
| 68 | "(STUBBED) called. pid={}, content_type={}, applet_resource_user_id={}", pid, | 72 | "(STUBBED) called. pid={}, content_type={}, start_posix_time={}, " |
| 69 | content_type, applet_resource_user_id); | 73 | "end_posix_time={}, applet_resource_user_id={}, total_entries={}", |
| 74 | pid, content_type, start_posix_time, end_posix_time, applet_resource_user_id, | ||
| 75 | total_entries); | ||
| 70 | 76 | ||
| 71 | IPC::ResponseBuilder rb{ctx, 3}; | 77 | IPC::ResponseBuilder rb{ctx, 3}; |
| 72 | rb.Push(RESULT_SUCCESS); | 78 | rb.Push(RESULT_SUCCESS); |
| 73 | rb.Push<s32>(0); | 79 | rb.Push(total_entries); |
| 74 | } | 80 | } |
| 75 | 81 | ||
| 76 | } // namespace Service::Capture | 82 | } // namespace Service::Capture |
diff --git a/src/core/hle/service/caps/caps_u.h b/src/core/hle/service/caps/caps_u.h index e6e0716ff..689364de4 100644 --- a/src/core/hle/service/caps/caps_u.h +++ b/src/core/hle/service/caps/caps_u.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | 1 | // Copyright 2020 yuzu Emulator Project |
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index f8e9df4b1..9365f27e1 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp | |||
| @@ -27,8 +27,8 @@ public: | |||
| 27 | {8, &ETicket::GetTitleKey, "GetTitleKey"}, | 27 | {8, &ETicket::GetTitleKey, "GetTitleKey"}, |
| 28 | {9, &ETicket::CountCommonTicket, "CountCommonTicket"}, | 28 | {9, &ETicket::CountCommonTicket, "CountCommonTicket"}, |
| 29 | {10, &ETicket::CountPersonalizedTicket, "CountPersonalizedTicket"}, | 29 | {10, &ETicket::CountPersonalizedTicket, "CountPersonalizedTicket"}, |
| 30 | {11, &ETicket::ListCommonTicket, "ListCommonTicket"}, | 30 | {11, &ETicket::ListCommonTicketRightsIds, "ListCommonTicketRightsIds"}, |
| 31 | {12, &ETicket::ListPersonalizedTicket, "ListPersonalizedTicket"}, | 31 | {12, &ETicket::ListPersonalizedTicketRightsIds, "ListPersonalizedTicketRightsIds"}, |
| 32 | {13, nullptr, "ListMissingPersonalizedTicket"}, | 32 | {13, nullptr, "ListMissingPersonalizedTicket"}, |
| 33 | {14, &ETicket::GetCommonTicketSize, "GetCommonTicketSize"}, | 33 | {14, &ETicket::GetCommonTicketSize, "GetCommonTicketSize"}, |
| 34 | {15, &ETicket::GetPersonalizedTicketSize, "GetPersonalizedTicketSize"}, | 34 | {15, &ETicket::GetPersonalizedTicketSize, "GetPersonalizedTicketSize"}, |
| @@ -55,7 +55,46 @@ public: | |||
| 55 | {36, nullptr, "DeleteAllInactiveELicenseRequiredPersonalizedTicket"}, | 55 | {36, nullptr, "DeleteAllInactiveELicenseRequiredPersonalizedTicket"}, |
| 56 | {37, nullptr, "OwnTicket2"}, | 56 | {37, nullptr, "OwnTicket2"}, |
| 57 | {38, nullptr, "OwnTicket3"}, | 57 | {38, nullptr, "OwnTicket3"}, |
| 58 | {501, nullptr, "Unknown501"}, | ||
| 59 | {502, nullptr, "Unknown502"}, | ||
| 58 | {503, nullptr, "GetTitleKey"}, | 60 | {503, nullptr, "GetTitleKey"}, |
| 61 | {504, nullptr, "Unknown504"}, | ||
| 62 | {508, nullptr, "Unknown508"}, | ||
| 63 | {509, nullptr, "Unknown509"}, | ||
| 64 | {510, nullptr, "Unknown510"}, | ||
| 65 | {511, nullptr, "Unknown511"}, | ||
| 66 | {1001, nullptr, "Unknown1001"}, | ||
| 67 | {1002, nullptr, "Unknown1001"}, | ||
| 68 | {1003, nullptr, "Unknown1003"}, | ||
| 69 | {1004, nullptr, "Unknown1004"}, | ||
| 70 | {1005, nullptr, "Unknown1005"}, | ||
| 71 | {1006, nullptr, "Unknown1006"}, | ||
| 72 | {1007, nullptr, "Unknown1007"}, | ||
| 73 | {1009, nullptr, "Unknown1009"}, | ||
| 74 | {1010, nullptr, "Unknown1010"}, | ||
| 75 | {1011, nullptr, "Unknown1011"}, | ||
| 76 | {1012, nullptr, "Unknown1012"}, | ||
| 77 | {1013, nullptr, "Unknown1013"}, | ||
| 78 | {1014, nullptr, "Unknown1014"}, | ||
| 79 | {1015, nullptr, "Unknown1015"}, | ||
| 80 | {1016, nullptr, "Unknown1016"}, | ||
| 81 | {1017, nullptr, "Unknown1017"}, | ||
| 82 | {1018, nullptr, "Unknown1018"}, | ||
| 83 | {1019, nullptr, "Unknown1019"}, | ||
| 84 | {1020, nullptr, "Unknown1020"}, | ||
| 85 | {1021, nullptr, "Unknown1021"}, | ||
| 86 | {1501, nullptr, "Unknown1501"}, | ||
| 87 | {1502, nullptr, "Unknown1502"}, | ||
| 88 | {1503, nullptr, "Unknown1503"}, | ||
| 89 | {1504, nullptr, "Unknown1504"}, | ||
| 90 | {1505, nullptr, "Unknown1505"}, | ||
| 91 | {2000, nullptr, "Unknown2000"}, | ||
| 92 | {2001, nullptr, "Unknown2001"}, | ||
| 93 | {2100, nullptr, "Unknown2100"}, | ||
| 94 | {2501, nullptr, "Unknown2501"}, | ||
| 95 | {2502, nullptr, "Unknown2502"}, | ||
| 96 | {3001, nullptr, "Unknown3001"}, | ||
| 97 | {3002, nullptr, "Unknown3002"}, | ||
| 59 | }; | 98 | }; |
| 60 | // clang-format on | 99 | // clang-format on |
| 61 | RegisterHandlers(functions); | 100 | RegisterHandlers(functions); |
| @@ -147,7 +186,7 @@ private: | |||
| 147 | rb.Push<u32>(count); | 186 | rb.Push<u32>(count); |
| 148 | } | 187 | } |
| 149 | 188 | ||
| 150 | void ListCommonTicket(Kernel::HLERequestContext& ctx) { | 189 | void ListCommonTicketRightsIds(Kernel::HLERequestContext& ctx) { |
| 151 | u32 out_entries; | 190 | u32 out_entries; |
| 152 | if (keys.GetCommonTickets().empty()) | 191 | if (keys.GetCommonTickets().empty()) |
| 153 | out_entries = 0; | 192 | out_entries = 0; |
| @@ -170,7 +209,7 @@ private: | |||
| 170 | rb.Push<u32>(out_entries); | 209 | rb.Push<u32>(out_entries); |
| 171 | } | 210 | } |
| 172 | 211 | ||
| 173 | void ListPersonalizedTicket(Kernel::HLERequestContext& ctx) { | 212 | void ListPersonalizedTicketRightsIds(Kernel::HLERequestContext& ctx) { |
| 174 | u32 out_entries; | 213 | u32 out_entries; |
| 175 | if (keys.GetPersonalizedTickets().empty()) | 214 | if (keys.GetPersonalizedTickets().empty()) |
| 176 | out_entries = 0; | 215 | out_entries = 0; |
diff --git a/src/core/hle/service/eupld/eupld.cpp b/src/core/hle/service/eupld/eupld.cpp index 2df30acee..0d6d244f4 100644 --- a/src/core/hle/service/eupld/eupld.cpp +++ b/src/core/hle/service/eupld/eupld.cpp | |||
| @@ -19,6 +19,7 @@ public: | |||
| 19 | {1, nullptr, "ImportCrt"}, | 19 | {1, nullptr, "ImportCrt"}, |
| 20 | {2, nullptr, "ImportPki"}, | 20 | {2, nullptr, "ImportPki"}, |
| 21 | {3, nullptr, "SetAutoUpload"}, | 21 | {3, nullptr, "SetAutoUpload"}, |
| 22 | {4, nullptr, "GetAutoUpload"}, | ||
| 22 | }; | 23 | }; |
| 23 | // clang-format on | 24 | // clang-format on |
| 24 | 25 | ||
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index c55d900e2..6fbee7efa 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -566,6 +566,14 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) { | |||
| 566 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; | 566 | connected_controllers[NPadIdToIndex(npad_id)].is_connected = false; |
| 567 | } | 567 | } |
| 568 | 568 | ||
| 569 | void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) { | ||
| 570 | gyroscope_zero_drift_mode = drift_mode; | ||
| 571 | } | ||
| 572 | |||
| 573 | Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const { | ||
| 574 | return gyroscope_zero_drift_mode; | ||
| 575 | } | ||
| 576 | |||
| 569 | void Controller_NPad::StartLRAssignmentMode() { | 577 | void Controller_NPad::StartLRAssignmentMode() { |
| 570 | // Nothing internally is used for lr assignment mode. Since we have the ability to set the | 578 | // Nothing internally is used for lr assignment mode. Since we have the ability to set the |
| 571 | // controller types from boot, it doesn't really matter about showing a selection screen | 579 | // controller types from boot, it doesn't really matter about showing a selection screen |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 931f03430..5d4c58a43 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -58,6 +58,12 @@ public: | |||
| 58 | }; | 58 | }; |
| 59 | static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); | 59 | static_assert(sizeof(Vibration) == 0x10, "Vibration is an invalid size"); |
| 60 | 60 | ||
| 61 | enum class GyroscopeZeroDriftMode : u32 { | ||
| 62 | Loose = 0, | ||
| 63 | Standard = 1, | ||
| 64 | Tight = 2, | ||
| 65 | }; | ||
| 66 | |||
| 61 | enum class NpadHoldType : u64 { | 67 | enum class NpadHoldType : u64 { |
| 62 | Vertical = 0, | 68 | Vertical = 0, |
| 63 | Horizontal = 1, | 69 | Horizontal = 1, |
| @@ -117,6 +123,8 @@ public: | |||
| 117 | 123 | ||
| 118 | void ConnectNPad(u32 npad_id); | 124 | void ConnectNPad(u32 npad_id); |
| 119 | void DisconnectNPad(u32 npad_id); | 125 | void DisconnectNPad(u32 npad_id); |
| 126 | void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode); | ||
| 127 | GyroscopeZeroDriftMode GetGyroscopeZeroDriftMode() const; | ||
| 120 | LedPattern GetLedPattern(u32 npad_id); | 128 | LedPattern GetLedPattern(u32 npad_id); |
| 121 | void SetVibrationEnabled(bool can_vibrate); | 129 | void SetVibrationEnabled(bool can_vibrate); |
| 122 | bool IsVibrationEnabled() const; | 130 | bool IsVibrationEnabled() const; |
| @@ -324,8 +332,8 @@ private: | |||
| 324 | std::array<Kernel::EventPair, 10> styleset_changed_events; | 332 | std::array<Kernel::EventPair, 10> styleset_changed_events; |
| 325 | Vibration last_processed_vibration{}; | 333 | Vibration last_processed_vibration{}; |
| 326 | std::array<ControllerHolder, 10> connected_controllers{}; | 334 | std::array<ControllerHolder, 10> connected_controllers{}; |
| 335 | GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; | ||
| 327 | bool can_controllers_vibrate{true}; | 336 | bool can_controllers_vibrate{true}; |
| 328 | |||
| 329 | std::array<ControllerPad, 10> npad_pad_states{}; | 337 | std::array<ControllerPad, 10> npad_pad_states{}; |
| 330 | bool is_in_lr_assignment_mode{false}; | 338 | bool is_in_lr_assignment_mode{false}; |
| 331 | Core::System& system; | 339 | Core::System& system; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 72a050de2..57d5edea7 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -185,8 +185,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { | |||
| 185 | {77, nullptr, "GetAccelerometerPlayMode"}, | 185 | {77, nullptr, "GetAccelerometerPlayMode"}, |
| 186 | {78, nullptr, "ResetAccelerometerPlayMode"}, | 186 | {78, nullptr, "ResetAccelerometerPlayMode"}, |
| 187 | {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"}, | 187 | {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"}, |
| 188 | {80, nullptr, "GetGyroscopeZeroDriftMode"}, | 188 | {80, &Hid::GetGyroscopeZeroDriftMode, "GetGyroscopeZeroDriftMode"}, |
| 189 | {81, nullptr, "ResetGyroscopeZeroDriftMode"}, | 189 | {81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"}, |
| 190 | {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"}, | 190 | {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"}, |
| 191 | {83, nullptr, "IsFirmwareUpdateAvailableForSixAxisSensor"}, | 191 | {83, nullptr, "IsFirmwareUpdateAvailableForSixAxisSensor"}, |
| 192 | {91, &Hid::ActivateGesture, "ActivateGesture"}, | 192 | {91, &Hid::ActivateGesture, "ActivateGesture"}, |
| @@ -230,15 +230,15 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { | |||
| 230 | {211, nullptr, "IsVibrationDeviceMounted"}, | 230 | {211, nullptr, "IsVibrationDeviceMounted"}, |
| 231 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, | 231 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, |
| 232 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, | 232 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, |
| 233 | {302, nullptr, "StopConsoleSixAxisSensor"}, | 233 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, |
| 234 | {303, nullptr, "ActivateSevenSixAxisSensor"}, | 234 | {303, &Hid::ActivateSevenSixAxisSensor, "ActivateSevenSixAxisSensor"}, |
| 235 | {304, nullptr, "StartSevenSixAxisSensor"}, | 235 | {304, &Hid::StartSevenSixAxisSensor, "StartSevenSixAxisSensor"}, |
| 236 | {305, &Hid::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"}, | 236 | {305, &Hid::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"}, |
| 237 | {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"}, | 237 | {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"}, |
| 238 | {307, nullptr, "FinalizeSevenSixAxisSensor"}, | 238 | {307, &Hid::FinalizeSevenSixAxisSensor, "FinalizeSevenSixAxisSensor"}, |
| 239 | {308, nullptr, "SetSevenSixAxisSensorFusionStrength"}, | 239 | {308, nullptr, "SetSevenSixAxisSensorFusionStrength"}, |
| 240 | {309, nullptr, "GetSevenSixAxisSensorFusionStrength"}, | 240 | {309, nullptr, "GetSevenSixAxisSensorFusionStrength"}, |
| 241 | {310, nullptr, "ResetSevenSixAxisSensorTimestamp"}, | 241 | {310, &Hid::ResetSevenSixAxisSensorTimestamp, "ResetSevenSixAxisSensorTimestamp"}, |
| 242 | {400, nullptr, "IsUsbFullKeyControllerEnabled"}, | 242 | {400, nullptr, "IsUsbFullKeyControllerEnabled"}, |
| 243 | {401, nullptr, "EnableUsbFullKeyController"}, | 243 | {401, nullptr, "EnableUsbFullKeyController"}, |
| 244 | {402, nullptr, "IsUsbFullKeyControllerConnected"}, | 244 | {402, nullptr, "IsUsbFullKeyControllerConnected"}, |
| @@ -374,6 +374,15 @@ void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { | |||
| 374 | rb.Push(RESULT_SUCCESS); | 374 | rb.Push(RESULT_SUCCESS); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { | ||
| 378 | IPC::RequestParser rp{ctx}; | ||
| 379 | const auto flags{rp.Pop<u32>()}; | ||
| 380 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); | ||
| 381 | |||
| 382 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 383 | rb.Push(RESULT_SUCCESS); | ||
| 384 | } | ||
| 385 | |||
| 377 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { | 386 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { |
| 378 | IPC::RequestParser rp{ctx}; | 387 | IPC::RequestParser rp{ctx}; |
| 379 | const auto unknown{rp.Pop<u32>()}; | 388 | const auto unknown{rp.Pop<u32>()}; |
| @@ -413,15 +422,59 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 413 | rb.Push(RESULT_SUCCESS); | 422 | rb.Push(RESULT_SUCCESS); |
| 414 | } | 423 | } |
| 415 | 424 | ||
| 425 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | ||
| 426 | IPC::RequestParser rp{ctx}; | ||
| 427 | const auto handle{rp.Pop<u32>()}; | ||
| 428 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 429 | |||
| 430 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | ||
| 431 | applet_resource_user_id); | ||
| 432 | |||
| 433 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 434 | rb.Push(RESULT_SUCCESS); | ||
| 435 | } | ||
| 436 | |||
| 416 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 437 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 417 | IPC::RequestParser rp{ctx}; | 438 | IPC::RequestParser rp{ctx}; |
| 418 | const auto handle{rp.Pop<u32>()}; | 439 | const auto handle{rp.Pop<u32>()}; |
| 419 | const auto drift_mode{rp.Pop<u32>()}; | 440 | const auto drift_mode{rp.Pop<u32>()}; |
| 420 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 441 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 421 | 442 | ||
| 422 | LOG_WARNING(Service_HID, | 443 | applet_resource->GetController<Controller_NPad>(HidController::NPad) |
| 423 | "(STUBBED) called, handle={}, drift_mode={}, applet_resource_user_id={}", handle, | 444 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode{drift_mode}); |
| 424 | drift_mode, applet_resource_user_id); | 445 | |
| 446 | LOG_DEBUG(Service_HID, "called, handle={}, drift_mode={}, applet_resource_user_id={}", handle, | ||
| 447 | drift_mode, applet_resource_user_id); | ||
| 448 | |||
| 449 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 450 | rb.Push(RESULT_SUCCESS); | ||
| 451 | } | ||
| 452 | |||
| 453 | void Hid::GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | ||
| 454 | IPC::RequestParser rp{ctx}; | ||
| 455 | const auto handle{rp.Pop<u32>()}; | ||
| 456 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 457 | |||
| 458 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | ||
| 459 | applet_resource_user_id); | ||
| 460 | |||
| 461 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 462 | rb.Push(RESULT_SUCCESS); | ||
| 463 | rb.Push<u32>( | ||
| 464 | static_cast<u32>(applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 465 | .GetGyroscopeZeroDriftMode())); | ||
| 466 | } | ||
| 467 | |||
| 468 | void Hid::ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | ||
| 469 | IPC::RequestParser rp{ctx}; | ||
| 470 | const auto handle{rp.Pop<u32>()}; | ||
| 471 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 472 | |||
| 473 | applet_resource->GetController<Controller_NPad>(HidController::NPad) | ||
| 474 | .SetGyroscopeZeroDriftMode(Controller_NPad::GyroscopeZeroDriftMode::Standard); | ||
| 475 | |||
| 476 | LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, | ||
| 477 | applet_resource_user_id); | ||
| 425 | 478 | ||
| 426 | IPC::ResponseBuilder rb{ctx, 2}; | 479 | IPC::ResponseBuilder rb{ctx, 2}; |
| 427 | rb.Push(RESULT_SUCCESS); | 480 | rb.Push(RESULT_SUCCESS); |
| @@ -832,33 +885,35 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 832 | rb.Push(RESULT_SUCCESS); | 885 | rb.Push(RESULT_SUCCESS); |
| 833 | } | 886 | } |
| 834 | 887 | ||
| 835 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | 888 | void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 836 | IPC::RequestParser rp{ctx}; | 889 | IPC::RequestParser rp{ctx}; |
| 837 | const auto handle{rp.Pop<u32>()}; | 890 | const auto handle{rp.Pop<u32>()}; |
| 891 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 838 | 892 | ||
| 839 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}", handle); | 893 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, |
| 894 | applet_resource_user_id); | ||
| 840 | 895 | ||
| 841 | IPC::ResponseBuilder rb{ctx, 2}; | 896 | IPC::ResponseBuilder rb{ctx, 2}; |
| 842 | rb.Push(RESULT_SUCCESS); | 897 | rb.Push(RESULT_SUCCESS); |
| 843 | } | 898 | } |
| 844 | 899 | ||
| 845 | void Hid::SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) { | 900 | void Hid::ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 846 | IPC::RequestParser rp{ctx}; | 901 | IPC::RequestParser rp{ctx}; |
| 847 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 902 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 848 | const auto unknown{rp.Pop<u32>()}; | ||
| 849 | 903 | ||
| 850 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, unknown={}", | 904 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", |
| 851 | applet_resource_user_id, unknown); | 905 | applet_resource_user_id); |
| 852 | 906 | ||
| 853 | IPC::ResponseBuilder rb{ctx, 2}; | 907 | IPC::ResponseBuilder rb{ctx, 2}; |
| 854 | rb.Push(RESULT_SUCCESS); | 908 | rb.Push(RESULT_SUCCESS); |
| 855 | } | 909 | } |
| 856 | 910 | ||
| 857 | void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { | 911 | void Hid::StartSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 858 | IPC::RequestParser rp{ctx}; | 912 | IPC::RequestParser rp{ctx}; |
| 859 | const auto unknown{rp.Pop<u32>()}; | 913 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 860 | 914 | ||
| 861 | LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}", unknown); | 915 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", |
| 916 | applet_resource_user_id); | ||
| 862 | 917 | ||
| 863 | IPC::ResponseBuilder rb{ctx, 2}; | 918 | IPC::ResponseBuilder rb{ctx, 2}; |
| 864 | rb.Push(RESULT_SUCCESS); | 919 | rb.Push(RESULT_SUCCESS); |
| @@ -882,10 +937,46 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 882 | rb.Push(RESULT_SUCCESS); | 937 | rb.Push(RESULT_SUCCESS); |
| 883 | } | 938 | } |
| 884 | 939 | ||
| 885 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { | 940 | void Hid::FinalizeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 886 | IPC::RequestParser rp{ctx}; | 941 | IPC::RequestParser rp{ctx}; |
| 887 | const auto flags{rp.Pop<u32>()}; | 942 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 888 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); | 943 | |
| 944 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", | ||
| 945 | applet_resource_user_id); | ||
| 946 | |||
| 947 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 948 | rb.Push(RESULT_SUCCESS); | ||
| 949 | } | ||
| 950 | |||
| 951 | void Hid::ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx) { | ||
| 952 | IPC::RequestParser rp{ctx}; | ||
| 953 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 954 | |||
| 955 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", | ||
| 956 | applet_resource_user_id); | ||
| 957 | |||
| 958 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 959 | rb.Push(RESULT_SUCCESS); | ||
| 960 | } | ||
| 961 | |||
| 962 | void Hid::SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) { | ||
| 963 | IPC::RequestParser rp{ctx}; | ||
| 964 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 965 | const auto is_palma_all_connectable{rp.Pop<bool>()}; | ||
| 966 | |||
| 967 | LOG_WARNING(Service_HID, | ||
| 968 | "(STUBBED) called, applet_resource_user_id={}, is_palma_all_connectable={}", | ||
| 969 | applet_resource_user_id, is_palma_all_connectable); | ||
| 970 | |||
| 971 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 972 | rb.Push(RESULT_SUCCESS); | ||
| 973 | } | ||
| 974 | |||
| 975 | void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { | ||
| 976 | IPC::RequestParser rp{ctx}; | ||
| 977 | const auto palma_boost_mode{rp.Pop<bool>()}; | ||
| 978 | |||
| 979 | LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode); | ||
| 889 | 980 | ||
| 890 | IPC::ResponseBuilder rb{ctx, 2}; | 981 | IPC::ResponseBuilder rb{ctx, 2}; |
| 891 | rb.Push(RESULT_SUCCESS); | 982 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index d481a75f8..6fb048360 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -91,10 +91,14 @@ private: | |||
| 91 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); | 91 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); |
| 92 | void ActivateMouse(Kernel::HLERequestContext& ctx); | 92 | void ActivateMouse(Kernel::HLERequestContext& ctx); |
| 93 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); | 93 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); |
| 94 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); | ||
| 94 | void ActivateGesture(Kernel::HLERequestContext& ctx); | 95 | void ActivateGesture(Kernel::HLERequestContext& ctx); |
| 95 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); | 96 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); |
| 96 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); | 97 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 98 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 97 | void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 99 | void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| 100 | void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | ||
| 101 | void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | ||
| 98 | void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); | 102 | void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx); |
| 99 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | 103 | void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); |
| 100 | void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); | 104 | void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx); |
| @@ -126,12 +130,15 @@ private: | |||
| 126 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); | 130 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); |
| 127 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 131 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 128 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 132 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 129 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); | 133 | void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 130 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); | 134 | void ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 131 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); | 135 | void StartSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 132 | void StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx); | 136 | void StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 133 | void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); | 137 | void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 134 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); | 138 | void FinalizeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 139 | void ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx); | ||
| 140 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); | ||
| 141 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); | ||
| 135 | 142 | ||
| 136 | std::shared_ptr<IAppletResource> applet_resource; | 143 | std::shared_ptr<IAppletResource> applet_resource; |
| 137 | Core::System& system; | 144 | Core::System& system; |
diff --git a/src/core/hle/service/lm/manager.cpp b/src/core/hle/service/lm/manager.cpp index b67081b86..3ee2374e7 100644 --- a/src/core/hle/service/lm/manager.cpp +++ b/src/core/hle/service/lm/manager.cpp | |||
| @@ -86,7 +86,8 @@ std::string FormatField(Field type, const std::vector<u8>& data) { | |||
| 86 | return Common::StringFromFixedZeroTerminatedBuffer( | 86 | return Common::StringFromFixedZeroTerminatedBuffer( |
| 87 | reinterpret_cast<const char*>(data.data()), data.size()); | 87 | reinterpret_cast<const char*>(data.data()), data.size()); |
| 88 | default: | 88 | default: |
| 89 | UNIMPLEMENTED(); | 89 | UNIMPLEMENTED_MSG("Unimplemented field type={}", type); |
| 90 | return ""; | ||
| 90 | } | 91 | } |
| 91 | } | 92 | } |
| 92 | 93 | ||
diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 4edff9cd8..56df5e925 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp | |||
| @@ -127,6 +127,13 @@ void LogSettings() { | |||
| 127 | LogSetting("Services_BCATBoxcatLocal", Settings::values.bcat_boxcat_local); | 127 | LogSetting("Services_BCATBoxcatLocal", Settings::values.bcat_boxcat_local); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | float Volume() { | ||
| 131 | if (values.audio_muted) { | ||
| 132 | return 0.0f; | ||
| 133 | } | ||
| 134 | return values.volume; | ||
| 135 | } | ||
| 136 | |||
| 130 | bool IsGPULevelExtreme() { | 137 | bool IsGPULevelExtreme() { |
| 131 | return values.gpu_accuracy == GPUAccuracy::Extreme; | 138 | return values.gpu_accuracy == GPUAccuracy::Extreme; |
| 132 | } | 139 | } |
diff --git a/src/core/settings.h b/src/core/settings.h index 33e1e06cd..a598ccbc1 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -459,6 +459,7 @@ struct Values { | |||
| 459 | bool use_dev_keys; | 459 | bool use_dev_keys; |
| 460 | 460 | ||
| 461 | // Audio | 461 | // Audio |
| 462 | bool audio_muted; | ||
| 462 | std::string sink_id; | 463 | std::string sink_id; |
| 463 | bool enable_audio_stretching; | 464 | bool enable_audio_stretching; |
| 464 | std::string audio_device_id; | 465 | std::string audio_device_id; |
| @@ -490,6 +491,8 @@ struct Values { | |||
| 490 | std::map<u64, std::vector<std::string>> disabled_addons; | 491 | std::map<u64, std::vector<std::string>> disabled_addons; |
| 491 | } extern values; | 492 | } extern values; |
| 492 | 493 | ||
| 494 | float Volume(); | ||
| 495 | |||
| 493 | bool IsGPULevelExtreme(); | 496 | bool IsGPULevelExtreme(); |
| 494 | bool IsGPULevelHigh(); | 497 | bool IsGPULevelHigh(); |
| 495 | 498 | ||
diff --git a/src/input_common/keyboard.cpp b/src/input_common/keyboard.cpp index 078374be5..afb8e6612 100644 --- a/src/input_common/keyboard.cpp +++ b/src/input_common/keyboard.cpp | |||
| @@ -76,7 +76,7 @@ std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage | |||
| 76 | int key_code = params.Get("code", 0); | 76 | int key_code = params.Get("code", 0); |
| 77 | std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list); | 77 | std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list); |
| 78 | key_button_list->AddKeyButton(key_code, button.get()); | 78 | key_button_list->AddKeyButton(key_code, button.get()); |
| 79 | return std::move(button); | 79 | return button; |
| 80 | } | 80 | } |
| 81 | 81 | ||
| 82 | void Keyboard::PressKey(int key_code) { | 82 | void Keyboard::PressKey(int key_code) { |
diff --git a/src/input_common/motion_emu.cpp b/src/input_common/motion_emu.cpp index 868251628..d4cdf76a3 100644 --- a/src/input_common/motion_emu.cpp +++ b/src/input_common/motion_emu.cpp | |||
| @@ -145,7 +145,7 @@ std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackag | |||
| 145 | // Previously created device is disconnected here. Having two motion devices for 3DS is not | 145 | // Previously created device is disconnected here. Having two motion devices for 3DS is not |
| 146 | // expected. | 146 | // expected. |
| 147 | current_device = device_wrapper->device; | 147 | current_device = device_wrapper->device; |
| 148 | return std::move(device_wrapper); | 148 | return device_wrapper; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | void MotionEmu::BeginTilt(int x, int y) { | 151 | void MotionEmu::BeginTilt(int x, int y) { |
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 099bb446e..2dc752aa9 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt | |||
| @@ -27,6 +27,8 @@ add_library(video_core STATIC | |||
| 27 | engines/shader_type.h | 27 | engines/shader_type.h |
| 28 | macro/macro.cpp | 28 | macro/macro.cpp |
| 29 | macro/macro.h | 29 | macro/macro.h |
| 30 | macro/macro_hle.cpp | ||
| 31 | macro/macro_hle.h | ||
| 30 | macro/macro_interpreter.cpp | 32 | macro/macro_interpreter.cpp |
| 31 | macro/macro_interpreter.h | 33 | macro/macro_interpreter.h |
| 32 | macro/macro_jit_x64.cpp | 34 | macro/macro_jit_x64.cpp |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 308d8b55f..cf8bdd021 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -41,16 +41,20 @@ class BufferCache { | |||
| 41 | static constexpr u64 BLOCK_PAGE_SIZE = 1ULL << BLOCK_PAGE_BITS; | 41 | static constexpr u64 BLOCK_PAGE_SIZE = 1ULL << BLOCK_PAGE_BITS; |
| 42 | 42 | ||
| 43 | public: | 43 | public: |
| 44 | using BufferInfo = std::pair<BufferType, u64>; | 44 | struct BufferInfo { |
| 45 | BufferType handle; | ||
| 46 | u64 offset; | ||
| 47 | u64 address; | ||
| 48 | }; | ||
| 45 | 49 | ||
| 46 | BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4, | 50 | BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4, |
| 47 | bool is_written = false, bool use_fast_cbuf = false) { | 51 | bool is_written = false, bool use_fast_cbuf = false) { |
| 48 | std::lock_guard lock{mutex}; | 52 | std::lock_guard lock{mutex}; |
| 49 | 53 | ||
| 50 | const auto& memory_manager = system.GPU().MemoryManager(); | 54 | auto& memory_manager = system.GPU().MemoryManager(); |
| 51 | const std::optional<VAddr> cpu_addr_opt = memory_manager.GpuToCpuAddress(gpu_addr); | 55 | const std::optional<VAddr> cpu_addr_opt = memory_manager.GpuToCpuAddress(gpu_addr); |
| 52 | if (!cpu_addr_opt) { | 56 | if (!cpu_addr_opt) { |
| 53 | return {GetEmptyBuffer(size), 0}; | 57 | return GetEmptyBuffer(size); |
| 54 | } | 58 | } |
| 55 | const VAddr cpu_addr = *cpu_addr_opt; | 59 | const VAddr cpu_addr = *cpu_addr_opt; |
| 56 | 60 | ||
| @@ -59,7 +63,6 @@ public: | |||
| 59 | constexpr std::size_t max_stream_size = 0x800; | 63 | constexpr std::size_t max_stream_size = 0x800; |
| 60 | if (use_fast_cbuf || size < max_stream_size) { | 64 | if (use_fast_cbuf || size < max_stream_size) { |
| 61 | if (!is_written && !IsRegionWritten(cpu_addr, cpu_addr + size - 1)) { | 65 | if (!is_written && !IsRegionWritten(cpu_addr, cpu_addr + size - 1)) { |
| 62 | auto& memory_manager = system.GPU().MemoryManager(); | ||
| 63 | const bool is_granular = memory_manager.IsGranularRange(gpu_addr, size); | 66 | const bool is_granular = memory_manager.IsGranularRange(gpu_addr, size); |
| 64 | if (use_fast_cbuf) { | 67 | if (use_fast_cbuf) { |
| 65 | u8* dest; | 68 | u8* dest; |
| @@ -89,7 +92,7 @@ public: | |||
| 89 | Buffer* const block = GetBlock(cpu_addr, size); | 92 | Buffer* const block = GetBlock(cpu_addr, size); |
| 90 | MapInterval* const map = MapAddress(block, gpu_addr, cpu_addr, size); | 93 | MapInterval* const map = MapAddress(block, gpu_addr, cpu_addr, size); |
| 91 | if (!map) { | 94 | if (!map) { |
| 92 | return {GetEmptyBuffer(size), 0}; | 95 | return GetEmptyBuffer(size); |
| 93 | } | 96 | } |
| 94 | if (is_written) { | 97 | if (is_written) { |
| 95 | map->MarkAsModified(true, GetModifiedTicks()); | 98 | map->MarkAsModified(true, GetModifiedTicks()); |
| @@ -102,7 +105,7 @@ public: | |||
| 102 | } | 105 | } |
| 103 | } | 106 | } |
| 104 | 107 | ||
| 105 | return {block->Handle(), static_cast<u64>(block->Offset(cpu_addr))}; | 108 | return BufferInfo{block->Handle(), block->Offset(cpu_addr), block->Address()}; |
| 106 | } | 109 | } |
| 107 | 110 | ||
| 108 | /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset. | 111 | /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset. |
| @@ -255,27 +258,17 @@ public: | |||
| 255 | committed_flushes.pop_front(); | 258 | committed_flushes.pop_front(); |
| 256 | } | 259 | } |
| 257 | 260 | ||
| 258 | virtual BufferType GetEmptyBuffer(std::size_t size) = 0; | 261 | virtual BufferInfo GetEmptyBuffer(std::size_t size) = 0; |
| 259 | 262 | ||
| 260 | protected: | 263 | protected: |
| 261 | explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | 264 | explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, |
| 262 | std::unique_ptr<StreamBuffer> stream_buffer_) | 265 | std::unique_ptr<StreamBuffer> stream_buffer) |
| 263 | : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer_)}, | 266 | : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer)} {} |
| 264 | stream_buffer_handle{stream_buffer->Handle()} {} | ||
| 265 | 267 | ||
| 266 | ~BufferCache() = default; | 268 | ~BufferCache() = default; |
| 267 | 269 | ||
| 268 | virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0; | 270 | virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0; |
| 269 | 271 | ||
| 270 | virtual void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 271 | const u8* data) = 0; | ||
| 272 | |||
| 273 | virtual void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 274 | u8* data) = 0; | ||
| 275 | |||
| 276 | virtual void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 277 | std::size_t dst_offset, std::size_t size) = 0; | ||
| 278 | |||
| 279 | virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { | 272 | virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { |
| 280 | return {}; | 273 | return {}; |
| 281 | } | 274 | } |
| @@ -337,11 +330,11 @@ private: | |||
| 337 | const VAddr cpu_addr_end = cpu_addr + size; | 330 | const VAddr cpu_addr_end = cpu_addr + size; |
| 338 | if (memory_manager.IsGranularRange(gpu_addr, size)) { | 331 | if (memory_manager.IsGranularRange(gpu_addr, size)) { |
| 339 | u8* host_ptr = memory_manager.GetPointer(gpu_addr); | 332 | u8* host_ptr = memory_manager.GetPointer(gpu_addr); |
| 340 | UploadBlockData(*block, block->Offset(cpu_addr), size, host_ptr); | 333 | block->Upload(block->Offset(cpu_addr), size, host_ptr); |
| 341 | } else { | 334 | } else { |
| 342 | staging_buffer.resize(size); | 335 | staging_buffer.resize(size); |
| 343 | memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size); | 336 | memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size); |
| 344 | UploadBlockData(*block, block->Offset(cpu_addr), size, staging_buffer.data()); | 337 | block->Upload(block->Offset(cpu_addr), size, staging_buffer.data()); |
| 345 | } | 338 | } |
| 346 | return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr)); | 339 | return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr)); |
| 347 | } | 340 | } |
| @@ -400,7 +393,7 @@ private: | |||
| 400 | } | 393 | } |
| 401 | staging_buffer.resize(size); | 394 | staging_buffer.resize(size); |
| 402 | system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size); | 395 | system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size); |
| 403 | UploadBlockData(*block, block->Offset(interval.lower()), size, staging_buffer.data()); | 396 | block->Upload(block->Offset(interval.lower()), size, staging_buffer.data()); |
| 404 | } | 397 | } |
| 405 | } | 398 | } |
| 406 | 399 | ||
| @@ -437,7 +430,7 @@ private: | |||
| 437 | 430 | ||
| 438 | const std::size_t size = map->end - map->start; | 431 | const std::size_t size = map->end - map->start; |
| 439 | staging_buffer.resize(size); | 432 | staging_buffer.resize(size); |
| 440 | DownloadBlockData(*block, block->Offset(map->start), size, staging_buffer.data()); | 433 | block->Download(block->Offset(map->start), size, staging_buffer.data()); |
| 441 | system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size); | 434 | system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size); |
| 442 | map->MarkAsModified(false, 0); | 435 | map->MarkAsModified(false, 0); |
| 443 | } | 436 | } |
| @@ -450,7 +443,7 @@ private: | |||
| 450 | 443 | ||
| 451 | buffer_ptr += size; | 444 | buffer_ptr += size; |
| 452 | buffer_offset += size; | 445 | buffer_offset += size; |
| 453 | return {stream_buffer_handle, uploaded_offset}; | 446 | return BufferInfo{stream_buffer->Handle(), uploaded_offset, stream_buffer->Address()}; |
| 454 | } | 447 | } |
| 455 | 448 | ||
| 456 | void AlignBuffer(std::size_t alignment) { | 449 | void AlignBuffer(std::size_t alignment) { |
| @@ -465,7 +458,7 @@ private: | |||
| 465 | const std::size_t new_size = old_size + BLOCK_PAGE_SIZE; | 458 | const std::size_t new_size = old_size + BLOCK_PAGE_SIZE; |
| 466 | const VAddr cpu_addr = buffer->CpuAddr(); | 459 | const VAddr cpu_addr = buffer->CpuAddr(); |
| 467 | std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size); | 460 | std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size); |
| 468 | CopyBlock(*buffer, *new_buffer, 0, 0, old_size); | 461 | new_buffer->CopyFrom(*buffer, 0, 0, old_size); |
| 469 | QueueDestruction(std::move(buffer)); | 462 | QueueDestruction(std::move(buffer)); |
| 470 | 463 | ||
| 471 | const VAddr cpu_addr_end = cpu_addr + new_size - 1; | 464 | const VAddr cpu_addr_end = cpu_addr + new_size - 1; |
| @@ -487,8 +480,8 @@ private: | |||
| 487 | const std::size_t new_size = size_1 + size_2; | 480 | const std::size_t new_size = size_1 + size_2; |
| 488 | 481 | ||
| 489 | std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size); | 482 | std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size); |
| 490 | CopyBlock(*first, *new_buffer, 0, new_buffer->Offset(first_addr), size_1); | 483 | new_buffer->CopyFrom(*first, 0, new_buffer->Offset(first_addr), size_1); |
| 491 | CopyBlock(*second, *new_buffer, 0, new_buffer->Offset(second_addr), size_2); | 484 | new_buffer->CopyFrom(*second, 0, new_buffer->Offset(second_addr), size_2); |
| 492 | QueueDestruction(std::move(first)); | 485 | QueueDestruction(std::move(first)); |
| 493 | QueueDestruction(std::move(second)); | 486 | QueueDestruction(std::move(second)); |
| 494 | 487 | ||
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index ea3c8a963..c01436295 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp | |||
| @@ -128,7 +128,7 @@ void Maxwell3D::CallMacroMethod(u32 method, const std::vector<u32>& parameters) | |||
| 128 | ((method - MacroRegistersStart) >> 1) % static_cast<u32>(macro_positions.size()); | 128 | ((method - MacroRegistersStart) >> 1) % static_cast<u32>(macro_positions.size()); |
| 129 | 129 | ||
| 130 | // Execute the current macro. | 130 | // Execute the current macro. |
| 131 | macro_engine->Execute(macro_positions[entry], parameters); | 131 | macro_engine->Execute(*this, macro_positions[entry], parameters); |
| 132 | if (mme_draw.current_mode != MMEDrawMode::Undefined) { | 132 | if (mme_draw.current_mode != MMEDrawMode::Undefined) { |
| 133 | FlushMMEInlineDraw(); | 133 | FlushMMEInlineDraw(); |
| 134 | } | 134 | } |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index d5fe25065..ef1618990 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -1418,6 +1418,14 @@ public: | |||
| 1418 | return execute_on; | 1418 | return execute_on; |
| 1419 | } | 1419 | } |
| 1420 | 1420 | ||
| 1421 | VideoCore::RasterizerInterface& GetRasterizer() { | ||
| 1422 | return rasterizer; | ||
| 1423 | } | ||
| 1424 | |||
| 1425 | const VideoCore::RasterizerInterface& GetRasterizer() const { | ||
| 1426 | return rasterizer; | ||
| 1427 | } | ||
| 1428 | |||
| 1421 | /// Notify a memory write has happened. | 1429 | /// Notify a memory write has happened. |
| 1422 | void OnMemoryWrite() { | 1430 | void OnMemoryWrite() { |
| 1423 | dirty.flags |= dirty.on_write_stores; | 1431 | dirty.flags |= dirty.on_write_stores; |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index e7cb87589..d374b73cf 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -661,6 +661,10 @@ union Instruction { | |||
| 661 | constexpr Instruction(u64 value) : value{value} {} | 661 | constexpr Instruction(u64 value) : value{value} {} |
| 662 | constexpr Instruction(const Instruction& instr) : value(instr.value) {} | 662 | constexpr Instruction(const Instruction& instr) : value(instr.value) {} |
| 663 | 663 | ||
| 664 | constexpr bool Bit(u64 offset) const { | ||
| 665 | return ((value >> offset) & 1) != 0; | ||
| 666 | } | ||
| 667 | |||
| 664 | BitField<0, 8, Register> gpr0; | 668 | BitField<0, 8, Register> gpr0; |
| 665 | BitField<8, 8, Register> gpr8; | 669 | BitField<8, 8, Register> gpr8; |
| 666 | union { | 670 | union { |
| @@ -1874,7 +1878,9 @@ public: | |||
| 1874 | HSETP2_C, | 1878 | HSETP2_C, |
| 1875 | HSETP2_R, | 1879 | HSETP2_R, |
| 1876 | HSETP2_IMM, | 1880 | HSETP2_IMM, |
| 1881 | HSET2_C, | ||
| 1877 | HSET2_R, | 1882 | HSET2_R, |
| 1883 | HSET2_IMM, | ||
| 1878 | POPC_C, | 1884 | POPC_C, |
| 1879 | POPC_R, | 1885 | POPC_R, |
| 1880 | POPC_IMM, | 1886 | POPC_IMM, |
| @@ -2194,7 +2200,9 @@ private: | |||
| 2194 | INST("0111111-1-------", Id::HSETP2_C, Type::HalfSetPredicate, "HSETP2_C"), | 2200 | INST("0111111-1-------", Id::HSETP2_C, Type::HalfSetPredicate, "HSETP2_C"), |
| 2195 | INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), | 2201 | INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), |
| 2196 | INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"), | 2202 | INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"), |
| 2203 | INST("0111110-1-------", Id::HSET2_C, Type::HalfSet, "HSET2_C"), | ||
| 2197 | INST("0101110100011---", Id::HSET2_R, Type::HalfSet, "HSET2_R"), | 2204 | INST("0101110100011---", Id::HSET2_R, Type::HalfSet, "HSET2_R"), |
| 2205 | INST("0111110-0-------", Id::HSET2_IMM, Type::HalfSet, "HSET2_IMM"), | ||
| 2198 | INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"), | 2206 | INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"), |
| 2199 | INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), | 2207 | INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), |
| 2200 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), | 2208 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), |
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp index 89077a2d8..ef7dad349 100644 --- a/src/video_core/macro/macro.cpp +++ b/src/video_core/macro/macro.cpp | |||
| @@ -2,23 +2,37 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <boost/container_hash/hash.hpp> | ||
| 5 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 6 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 7 | #include "core/settings.h" | 8 | #include "core/settings.h" |
| 9 | #include "video_core/engines/maxwell_3d.h" | ||
| 8 | #include "video_core/macro/macro.h" | 10 | #include "video_core/macro/macro.h" |
| 11 | #include "video_core/macro/macro_hle.h" | ||
| 9 | #include "video_core/macro/macro_interpreter.h" | 12 | #include "video_core/macro/macro_interpreter.h" |
| 10 | #include "video_core/macro/macro_jit_x64.h" | 13 | #include "video_core/macro/macro_jit_x64.h" |
| 11 | 14 | ||
| 12 | namespace Tegra { | 15 | namespace Tegra { |
| 13 | 16 | ||
| 17 | MacroEngine::MacroEngine(Engines::Maxwell3D& maxwell3d) | ||
| 18 | : hle_macros{std::make_unique<Tegra::HLEMacro>(maxwell3d)} {} | ||
| 19 | |||
| 20 | MacroEngine::~MacroEngine() = default; | ||
| 21 | |||
| 14 | void MacroEngine::AddCode(u32 method, u32 data) { | 22 | void MacroEngine::AddCode(u32 method, u32 data) { |
| 15 | uploaded_macro_code[method].push_back(data); | 23 | uploaded_macro_code[method].push_back(data); |
| 16 | } | 24 | } |
| 17 | 25 | ||
| 18 | void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) { | 26 | void MacroEngine::Execute(Engines::Maxwell3D& maxwell3d, u32 method, |
| 27 | const std::vector<u32>& parameters) { | ||
| 19 | auto compiled_macro = macro_cache.find(method); | 28 | auto compiled_macro = macro_cache.find(method); |
| 20 | if (compiled_macro != macro_cache.end()) { | 29 | if (compiled_macro != macro_cache.end()) { |
| 21 | compiled_macro->second->Execute(parameters, method); | 30 | const auto& cache_info = compiled_macro->second; |
| 31 | if (cache_info.has_hle_program) { | ||
| 32 | cache_info.hle_program->Execute(parameters, method); | ||
| 33 | } else { | ||
| 34 | cache_info.lle_program->Execute(parameters, method); | ||
| 35 | } | ||
| 22 | } else { | 36 | } else { |
| 23 | // Macro not compiled, check if it's uploaded and if so, compile it | 37 | // Macro not compiled, check if it's uploaded and if so, compile it |
| 24 | auto macro_code = uploaded_macro_code.find(method); | 38 | auto macro_code = uploaded_macro_code.find(method); |
| @@ -26,8 +40,21 @@ void MacroEngine::Execute(u32 method, const std::vector<u32>& parameters) { | |||
| 26 | UNREACHABLE_MSG("Macro 0x{0:x} was not uploaded", method); | 40 | UNREACHABLE_MSG("Macro 0x{0:x} was not uploaded", method); |
| 27 | return; | 41 | return; |
| 28 | } | 42 | } |
| 29 | macro_cache[method] = Compile(macro_code->second); | 43 | auto& cache_info = macro_cache[method]; |
| 30 | macro_cache[method]->Execute(parameters, method); | 44 | cache_info.hash = boost::hash_value(macro_code->second); |
| 45 | cache_info.lle_program = Compile(macro_code->second); | ||
| 46 | |||
| 47 | auto hle_program = hle_macros->GetHLEProgram(cache_info.hash); | ||
| 48 | if (hle_program.has_value()) { | ||
| 49 | cache_info.has_hle_program = true; | ||
| 50 | cache_info.hle_program = std::move(hle_program.value()); | ||
| 51 | } | ||
| 52 | |||
| 53 | if (cache_info.has_hle_program) { | ||
| 54 | cache_info.hle_program->Execute(parameters, method); | ||
| 55 | } else { | ||
| 56 | cache_info.lle_program->Execute(parameters, method); | ||
| 57 | } | ||
| 31 | } | 58 | } |
| 32 | } | 59 | } |
| 33 | 60 | ||
diff --git a/src/video_core/macro/macro.h b/src/video_core/macro/macro.h index b76ed891f..4d00b84b0 100644 --- a/src/video_core/macro/macro.h +++ b/src/video_core/macro/macro.h | |||
| @@ -11,9 +11,11 @@ | |||
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | 12 | ||
| 13 | namespace Tegra { | 13 | namespace Tegra { |
| 14 | |||
| 14 | namespace Engines { | 15 | namespace Engines { |
| 15 | class Maxwell3D; | 16 | class Maxwell3D; |
| 16 | } | 17 | } |
| 18 | |||
| 17 | namespace Macro { | 19 | namespace Macro { |
| 18 | constexpr std::size_t NUM_MACRO_REGISTERS = 8; | 20 | constexpr std::size_t NUM_MACRO_REGISTERS = 8; |
| 19 | enum class Operation : u32 { | 21 | enum class Operation : u32 { |
| @@ -94,6 +96,8 @@ union MethodAddress { | |||
| 94 | 96 | ||
| 95 | } // namespace Macro | 97 | } // namespace Macro |
| 96 | 98 | ||
| 99 | class HLEMacro; | ||
| 100 | |||
| 97 | class CachedMacro { | 101 | class CachedMacro { |
| 98 | public: | 102 | public: |
| 99 | virtual ~CachedMacro() = default; | 103 | virtual ~CachedMacro() = default; |
| @@ -107,20 +111,29 @@ public: | |||
| 107 | 111 | ||
| 108 | class MacroEngine { | 112 | class MacroEngine { |
| 109 | public: | 113 | public: |
| 110 | virtual ~MacroEngine() = default; | 114 | explicit MacroEngine(Engines::Maxwell3D& maxwell3d); |
| 115 | virtual ~MacroEngine(); | ||
| 111 | 116 | ||
| 112 | // Store the uploaded macro code to compile them when they're called. | 117 | // Store the uploaded macro code to compile them when they're called. |
| 113 | void AddCode(u32 method, u32 data); | 118 | void AddCode(u32 method, u32 data); |
| 114 | 119 | ||
| 115 | // Compiles the macro if its not in the cache, and executes the compiled macro | 120 | // Compiles the macro if its not in the cache, and executes the compiled macro |
| 116 | void Execute(u32 method, const std::vector<u32>& parameters); | 121 | void Execute(Engines::Maxwell3D& maxwell3d, u32 method, const std::vector<u32>& parameters); |
| 117 | 122 | ||
| 118 | protected: | 123 | protected: |
| 119 | virtual std::unique_ptr<CachedMacro> Compile(const std::vector<u32>& code) = 0; | 124 | virtual std::unique_ptr<CachedMacro> Compile(const std::vector<u32>& code) = 0; |
| 120 | 125 | ||
| 121 | private: | 126 | private: |
| 122 | std::unordered_map<u32, std::unique_ptr<CachedMacro>> macro_cache; | 127 | struct CacheInfo { |
| 128 | std::unique_ptr<CachedMacro> lle_program{}; | ||
| 129 | std::unique_ptr<CachedMacro> hle_program{}; | ||
| 130 | u64 hash{}; | ||
| 131 | bool has_hle_program{}; | ||
| 132 | }; | ||
| 133 | |||
| 134 | std::unordered_map<u32, CacheInfo> macro_cache; | ||
| 123 | std::unordered_map<u32, std::vector<u32>> uploaded_macro_code; | 135 | std::unordered_map<u32, std::vector<u32>> uploaded_macro_code; |
| 136 | std::unique_ptr<HLEMacro> hle_macros; | ||
| 124 | }; | 137 | }; |
| 125 | 138 | ||
| 126 | std::unique_ptr<MacroEngine> GetMacroEngine(Engines::Maxwell3D& maxwell3d); | 139 | std::unique_ptr<MacroEngine> GetMacroEngine(Engines::Maxwell3D& maxwell3d); |
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp new file mode 100644 index 000000000..410f99018 --- /dev/null +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -0,0 +1,113 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <array> | ||
| 6 | #include <vector> | ||
| 7 | #include "video_core/engines/maxwell_3d.h" | ||
| 8 | #include "video_core/macro/macro_hle.h" | ||
| 9 | #include "video_core/rasterizer_interface.h" | ||
| 10 | |||
| 11 | namespace Tegra { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | // HLE'd functions | ||
| 15 | static void HLE_771BB18C62444DA0(Engines::Maxwell3D& maxwell3d, | ||
| 16 | const std::vector<u32>& parameters) { | ||
| 17 | const u32 instance_count = parameters[2] & maxwell3d.GetRegisterValue(0xD1B); | ||
| 18 | |||
| 19 | maxwell3d.regs.draw.topology.Assign( | ||
| 20 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & | ||
| 21 | ~(0x3ffffff << 26))); | ||
| 22 | maxwell3d.regs.vb_base_instance = parameters[5]; | ||
| 23 | maxwell3d.mme_draw.instance_count = instance_count; | ||
| 24 | maxwell3d.regs.vb_element_base = parameters[3]; | ||
| 25 | maxwell3d.regs.index_array.count = parameters[1]; | ||
| 26 | maxwell3d.regs.index_array.first = parameters[4]; | ||
| 27 | |||
| 28 | if (maxwell3d.ShouldExecute()) { | ||
| 29 | maxwell3d.GetRasterizer().Draw(true, true); | ||
| 30 | } | ||
| 31 | maxwell3d.regs.index_array.count = 0; | ||
| 32 | maxwell3d.mme_draw.instance_count = 0; | ||
| 33 | maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; | ||
| 34 | } | ||
| 35 | |||
| 36 | static void HLE_0D61FC9FAAC9FCAD(Engines::Maxwell3D& maxwell3d, | ||
| 37 | const std::vector<u32>& parameters) { | ||
| 38 | const u32 count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | ||
| 39 | |||
| 40 | maxwell3d.regs.vertex_buffer.first = parameters[3]; | ||
| 41 | maxwell3d.regs.vertex_buffer.count = parameters[1]; | ||
| 42 | maxwell3d.regs.vb_base_instance = parameters[4]; | ||
| 43 | maxwell3d.regs.draw.topology.Assign( | ||
| 44 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); | ||
| 45 | maxwell3d.mme_draw.instance_count = count; | ||
| 46 | |||
| 47 | if (maxwell3d.ShouldExecute()) { | ||
| 48 | maxwell3d.GetRasterizer().Draw(false, true); | ||
| 49 | } | ||
| 50 | maxwell3d.regs.vertex_buffer.count = 0; | ||
| 51 | maxwell3d.mme_draw.instance_count = 0; | ||
| 52 | maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; | ||
| 53 | } | ||
| 54 | |||
| 55 | static void HLE_0217920100488FF7(Engines::Maxwell3D& maxwell3d, | ||
| 56 | const std::vector<u32>& parameters) { | ||
| 57 | const u32 instance_count = (maxwell3d.GetRegisterValue(0xD1B) & parameters[2]); | ||
| 58 | const u32 element_base = parameters[4]; | ||
| 59 | const u32 base_instance = parameters[5]; | ||
| 60 | maxwell3d.regs.index_array.first = parameters[3]; | ||
| 61 | maxwell3d.regs.reg_array[0x446] = element_base; // vertex id base? | ||
| 62 | maxwell3d.regs.index_array.count = parameters[1]; | ||
| 63 | maxwell3d.regs.vb_element_base = element_base; | ||
| 64 | maxwell3d.regs.vb_base_instance = base_instance; | ||
| 65 | maxwell3d.mme_draw.instance_count = instance_count; | ||
| 66 | maxwell3d.CallMethodFromMME(0x8e3, 0x640); | ||
| 67 | maxwell3d.CallMethodFromMME(0x8e4, element_base); | ||
| 68 | maxwell3d.CallMethodFromMME(0x8e5, base_instance); | ||
| 69 | maxwell3d.regs.draw.topology.Assign( | ||
| 70 | static_cast<Tegra::Engines::Maxwell3D::Regs::PrimitiveTopology>(parameters[0])); | ||
| 71 | if (maxwell3d.ShouldExecute()) { | ||
| 72 | maxwell3d.GetRasterizer().Draw(true, true); | ||
| 73 | } | ||
| 74 | maxwell3d.regs.reg_array[0x446] = 0x0; // vertex id base? | ||
| 75 | maxwell3d.regs.index_array.count = 0; | ||
| 76 | maxwell3d.regs.vb_element_base = 0x0; | ||
| 77 | maxwell3d.regs.vb_base_instance = 0x0; | ||
| 78 | maxwell3d.mme_draw.instance_count = 0; | ||
| 79 | maxwell3d.CallMethodFromMME(0x8e3, 0x640); | ||
| 80 | maxwell3d.CallMethodFromMME(0x8e4, 0x0); | ||
| 81 | maxwell3d.CallMethodFromMME(0x8e5, 0x0); | ||
| 82 | maxwell3d.mme_draw.current_mode = Engines::Maxwell3D::MMEDrawMode::Undefined; | ||
| 83 | } | ||
| 84 | } // namespace | ||
| 85 | |||
| 86 | constexpr std::array<std::pair<u64, HLEFunction>, 3> hle_funcs{{ | ||
| 87 | std::make_pair<u64, HLEFunction>(0x771BB18C62444DA0, &HLE_771BB18C62444DA0), | ||
| 88 | std::make_pair<u64, HLEFunction>(0x0D61FC9FAAC9FCAD, &HLE_0D61FC9FAAC9FCAD), | ||
| 89 | std::make_pair<u64, HLEFunction>(0x0217920100488FF7, &HLE_0217920100488FF7), | ||
| 90 | }}; | ||
| 91 | |||
| 92 | HLEMacro::HLEMacro(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} | ||
| 93 | HLEMacro::~HLEMacro() = default; | ||
| 94 | |||
| 95 | std::optional<std::unique_ptr<CachedMacro>> HLEMacro::GetHLEProgram(u64 hash) const { | ||
| 96 | const auto it = std::find_if(hle_funcs.cbegin(), hle_funcs.cend(), | ||
| 97 | [hash](const auto& pair) { return pair.first == hash; }); | ||
| 98 | if (it == hle_funcs.end()) { | ||
| 99 | return std::nullopt; | ||
| 100 | } | ||
| 101 | return std::make_unique<HLEMacroImpl>(maxwell3d, it->second); | ||
| 102 | } | ||
| 103 | |||
| 104 | HLEMacroImpl::~HLEMacroImpl() = default; | ||
| 105 | |||
| 106 | HLEMacroImpl::HLEMacroImpl(Engines::Maxwell3D& maxwell3d, HLEFunction func) | ||
| 107 | : maxwell3d(maxwell3d), func(func) {} | ||
| 108 | |||
| 109 | void HLEMacroImpl::Execute(const std::vector<u32>& parameters, u32 method) { | ||
| 110 | func(maxwell3d, parameters); | ||
| 111 | } | ||
| 112 | |||
| 113 | } // namespace Tegra | ||
diff --git a/src/video_core/macro/macro_hle.h b/src/video_core/macro/macro_hle.h new file mode 100644 index 000000000..37af875a0 --- /dev/null +++ b/src/video_core/macro/macro_hle.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <optional> | ||
| 9 | #include <vector> | ||
| 10 | #include "common/common_types.h" | ||
| 11 | #include "video_core/macro/macro.h" | ||
| 12 | |||
| 13 | namespace Tegra { | ||
| 14 | |||
| 15 | namespace Engines { | ||
| 16 | class Maxwell3D; | ||
| 17 | } | ||
| 18 | |||
| 19 | using HLEFunction = void (*)(Engines::Maxwell3D& maxwell3d, const std::vector<u32>& parameters); | ||
| 20 | |||
| 21 | class HLEMacro { | ||
| 22 | public: | ||
| 23 | explicit HLEMacro(Engines::Maxwell3D& maxwell3d); | ||
| 24 | ~HLEMacro(); | ||
| 25 | |||
| 26 | std::optional<std::unique_ptr<CachedMacro>> GetHLEProgram(u64 hash) const; | ||
| 27 | |||
| 28 | private: | ||
| 29 | Engines::Maxwell3D& maxwell3d; | ||
| 30 | }; | ||
| 31 | |||
| 32 | class HLEMacroImpl : public CachedMacro { | ||
| 33 | public: | ||
| 34 | explicit HLEMacroImpl(Engines::Maxwell3D& maxwell3d, HLEFunction func); | ||
| 35 | ~HLEMacroImpl(); | ||
| 36 | |||
| 37 | void Execute(const std::vector<u32>& parameters, u32 method) override; | ||
| 38 | |||
| 39 | private: | ||
| 40 | Engines::Maxwell3D& maxwell3d; | ||
| 41 | HLEFunction func; | ||
| 42 | }; | ||
| 43 | |||
| 44 | } // namespace Tegra | ||
diff --git a/src/video_core/macro/macro_interpreter.cpp b/src/video_core/macro/macro_interpreter.cpp index 5edff27aa..aa5256419 100644 --- a/src/video_core/macro/macro_interpreter.cpp +++ b/src/video_core/macro/macro_interpreter.cpp | |||
| @@ -11,7 +11,8 @@ | |||
| 11 | MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192)); | 11 | MICROPROFILE_DEFINE(MacroInterp, "GPU", "Execute macro interpreter", MP_RGB(128, 128, 192)); |
| 12 | 12 | ||
| 13 | namespace Tegra { | 13 | namespace Tegra { |
| 14 | MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} | 14 | MacroInterpreter::MacroInterpreter(Engines::Maxwell3D& maxwell3d) |
| 15 | : MacroEngine::MacroEngine(maxwell3d), maxwell3d(maxwell3d) {} | ||
| 15 | 16 | ||
| 16 | std::unique_ptr<CachedMacro> MacroInterpreter::Compile(const std::vector<u32>& code) { | 17 | std::unique_ptr<CachedMacro> MacroInterpreter::Compile(const std::vector<u32>& code) { |
| 17 | return std::make_unique<MacroInterpreterImpl>(maxwell3d, code); | 18 | return std::make_unique<MacroInterpreterImpl>(maxwell3d, code); |
diff --git a/src/video_core/macro/macro_jit_x64.cpp b/src/video_core/macro/macro_jit_x64.cpp index d4a97ec7b..07292702f 100644 --- a/src/video_core/macro/macro_jit_x64.cpp +++ b/src/video_core/macro/macro_jit_x64.cpp | |||
| @@ -28,7 +28,8 @@ static const std::bitset<32> PERSISTENT_REGISTERS = Common::X64::BuildRegSet({ | |||
| 28 | BRANCH_HOLDER, | 28 | BRANCH_HOLDER, |
| 29 | }); | 29 | }); |
| 30 | 30 | ||
| 31 | MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d) : maxwell3d(maxwell3d) {} | 31 | MacroJITx64::MacroJITx64(Engines::Maxwell3D& maxwell3d) |
| 32 | : MacroEngine::MacroEngine(maxwell3d), maxwell3d(maxwell3d) {} | ||
| 32 | 33 | ||
| 33 | std::unique_ptr<CachedMacro> MacroJITx64::Compile(const std::vector<u32>& code) { | 34 | std::unique_ptr<CachedMacro> MacroJITx64::Compile(const std::vector<u32>& code) { |
| 34 | return std::make_unique<MacroJITx64Impl>(maxwell3d, code); | 35 | return std::make_unique<MacroJITx64Impl>(maxwell3d, code); |
| @@ -54,13 +55,15 @@ void MacroJITx64Impl::Compile_ALU(Macro::Opcode opcode) { | |||
| 54 | const bool is_a_zero = opcode.src_a == 0; | 55 | const bool is_a_zero = opcode.src_a == 0; |
| 55 | const bool is_b_zero = opcode.src_b == 0; | 56 | const bool is_b_zero = opcode.src_b == 0; |
| 56 | const bool valid_operation = !is_a_zero && !is_b_zero; | 57 | const bool valid_operation = !is_a_zero && !is_b_zero; |
| 57 | const bool is_move_operation = !is_a_zero && is_b_zero; | 58 | [[maybe_unused]] const bool is_move_operation = !is_a_zero && is_b_zero; |
| 58 | const bool has_zero_register = is_a_zero || is_b_zero; | 59 | const bool has_zero_register = is_a_zero || is_b_zero; |
| 60 | const bool no_zero_reg_skip = opcode.alu_operation == Macro::ALUOperation::AddWithCarry || | ||
| 61 | opcode.alu_operation == Macro::ALUOperation::SubtractWithBorrow; | ||
| 59 | 62 | ||
| 60 | Xbyak::Reg32 src_a; | 63 | Xbyak::Reg32 src_a; |
| 61 | Xbyak::Reg32 src_b; | 64 | Xbyak::Reg32 src_b; |
| 62 | 65 | ||
| 63 | if (!optimizer.zero_reg_skip) { | 66 | if (!optimizer.zero_reg_skip || no_zero_reg_skip) { |
| 64 | src_a = Compile_GetRegister(opcode.src_a, RESULT); | 67 | src_a = Compile_GetRegister(opcode.src_a, RESULT); |
| 65 | src_b = Compile_GetRegister(opcode.src_b, eax); | 68 | src_b = Compile_GetRegister(opcode.src_b, eax); |
| 66 | } else { | 69 | } else { |
| @@ -71,7 +74,6 @@ void MacroJITx64Impl::Compile_ALU(Macro::Opcode opcode) { | |||
| 71 | src_b = Compile_GetRegister(opcode.src_b, eax); | 74 | src_b = Compile_GetRegister(opcode.src_b, eax); |
| 72 | } | 75 | } |
| 73 | } | 76 | } |
| 74 | Xbyak::Label skip_carry{}; | ||
| 75 | 77 | ||
| 76 | bool has_emitted = false; | 78 | bool has_emitted = false; |
| 77 | 79 | ||
| @@ -183,7 +185,8 @@ void MacroJITx64Impl::Compile_AddImmediate(Macro::Opcode opcode) { | |||
| 183 | opcode.result_operation == Macro::ResultOperation::MoveAndSetMethod) { | 185 | opcode.result_operation == Macro::ResultOperation::MoveAndSetMethod) { |
| 184 | if (next_opcode.has_value()) { | 186 | if (next_opcode.has_value()) { |
| 185 | const auto next = *next_opcode; | 187 | const auto next = *next_opcode; |
| 186 | if (next.result_operation == Macro::ResultOperation::MoveAndSetMethod) { | 188 | if (next.result_operation == Macro::ResultOperation::MoveAndSetMethod && |
| 189 | opcode.dst == next.dst) { | ||
| 187 | return; | 190 | return; |
| 188 | } | 191 | } |
| 189 | } | 192 | } |
| @@ -237,10 +240,10 @@ void MacroJITx64Impl::Compile_ExtractInsert(Macro::Opcode opcode) { | |||
| 237 | } | 240 | } |
| 238 | 241 | ||
| 239 | void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) { | 242 | void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) { |
| 240 | auto dst = Compile_GetRegister(opcode.src_a, eax); | 243 | const auto dst = Compile_GetRegister(opcode.src_a, ecx); |
| 241 | auto src = Compile_GetRegister(opcode.src_b, RESULT); | 244 | const auto src = Compile_GetRegister(opcode.src_b, RESULT); |
| 242 | 245 | ||
| 243 | shr(src, al); | 246 | shr(src, dst.cvt8()); |
| 244 | if (opcode.bf_size != 0 && opcode.bf_size != 31) { | 247 | if (opcode.bf_size != 0 && opcode.bf_size != 31) { |
| 245 | and_(src, opcode.GetBitfieldMask()); | 248 | and_(src, opcode.GetBitfieldMask()); |
| 246 | } else if (opcode.bf_size == 0) { | 249 | } else if (opcode.bf_size == 0) { |
| @@ -256,8 +259,8 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) { | |||
| 256 | } | 259 | } |
| 257 | 260 | ||
| 258 | void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) { | 261 | void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) { |
| 259 | auto dst = Compile_GetRegister(opcode.src_a, eax); | 262 | const auto dst = Compile_GetRegister(opcode.src_a, ecx); |
| 260 | auto src = Compile_GetRegister(opcode.src_b, RESULT); | 263 | const auto src = Compile_GetRegister(opcode.src_b, RESULT); |
| 261 | 264 | ||
| 262 | if (opcode.bf_src_bit != 0) { | 265 | if (opcode.bf_src_bit != 0) { |
| 263 | shr(src, opcode.bf_src_bit); | 266 | shr(src, opcode.bf_src_bit); |
| @@ -266,16 +269,9 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) { | |||
| 266 | if (opcode.bf_size != 31) { | 269 | if (opcode.bf_size != 31) { |
| 267 | and_(src, opcode.GetBitfieldMask()); | 270 | and_(src, opcode.GetBitfieldMask()); |
| 268 | } | 271 | } |
| 269 | shl(src, al); | 272 | shl(src, dst.cvt8()); |
| 270 | Compile_ProcessResult(opcode.result_operation, opcode.dst); | ||
| 271 | } | ||
| 272 | 273 | ||
| 273 | static u32 Read(Engines::Maxwell3D* maxwell3d, u32 method) { | 274 | Compile_ProcessResult(opcode.result_operation, opcode.dst); |
| 274 | return maxwell3d->GetRegisterValue(method); | ||
| 275 | } | ||
| 276 | |||
| 277 | static void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { | ||
| 278 | maxwell3d->CallMethodFromMME(method_address.address, value); | ||
| 279 | } | 275 | } |
| 280 | 276 | ||
| 281 | void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { | 277 | void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { |
| @@ -295,15 +291,27 @@ void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) { | |||
| 295 | sub(result, opcode.immediate * -1); | 291 | sub(result, opcode.immediate * -1); |
| 296 | } | 292 | } |
| 297 | } | 293 | } |
| 298 | Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); | 294 | |
| 299 | mov(Common::X64::ABI_PARAM1, qword[STATE]); | 295 | // Equivalent to Engines::Maxwell3D::GetRegisterValue: |
| 300 | mov(Common::X64::ABI_PARAM2, RESULT); | 296 | if (optimizer.enable_asserts) { |
| 301 | Common::X64::CallFarFunction(*this, &Read); | 297 | Xbyak::Label pass_range_check; |
| 302 | Common::X64::ABI_PopRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); | 298 | cmp(RESULT, static_cast<u32>(Engines::Maxwell3D::Regs::NUM_REGS)); |
| 303 | mov(RESULT, Common::X64::ABI_RETURN.cvt32()); | 299 | jb(pass_range_check); |
| 300 | int3(); | ||
| 301 | L(pass_range_check); | ||
| 302 | } | ||
| 303 | mov(rax, qword[STATE]); | ||
| 304 | mov(RESULT, | ||
| 305 | dword[rax + offsetof(Engines::Maxwell3D, regs) + | ||
| 306 | offsetof(Engines::Maxwell3D::Regs, reg_array) + RESULT.cvt64() * sizeof(u32)]); | ||
| 307 | |||
| 304 | Compile_ProcessResult(opcode.result_operation, opcode.dst); | 308 | Compile_ProcessResult(opcode.result_operation, opcode.dst); |
| 305 | } | 309 | } |
| 306 | 310 | ||
| 311 | static void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) { | ||
| 312 | maxwell3d->CallMethodFromMME(method_address.address, value); | ||
| 313 | } | ||
| 314 | |||
| 307 | void Tegra::MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { | 315 | void Tegra::MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) { |
| 308 | Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); | 316 | Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0); |
| 309 | mov(Common::X64::ABI_PARAM1, qword[STATE]); | 317 | mov(Common::X64::ABI_PARAM1, qword[STATE]); |
| @@ -435,6 +443,9 @@ void MacroJITx64Impl::Compile() { | |||
| 435 | // one if our register isn't "dirty" | 443 | // one if our register isn't "dirty" |
| 436 | optimizer.optimize_for_method_move = true; | 444 | optimizer.optimize_for_method_move = true; |
| 437 | 445 | ||
| 446 | // Enable run-time assertions in JITted code | ||
| 447 | optimizer.enable_asserts = false; | ||
| 448 | |||
| 438 | // Check to see if we can skip emitting certain instructions | 449 | // Check to see if we can skip emitting certain instructions |
| 439 | Optimizer_ScanFlags(); | 450 | Optimizer_ScanFlags(); |
| 440 | 451 | ||
| @@ -543,7 +554,7 @@ Xbyak::Reg32 MacroJITx64Impl::Compile_GetRegister(u32 index, Xbyak::Reg32 dst) { | |||
| 543 | } | 554 | } |
| 544 | 555 | ||
| 545 | void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u32 reg) { | 556 | void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u32 reg) { |
| 546 | auto SetRegister = [=](u32 reg, Xbyak::Reg32 result) { | 557 | const auto SetRegister = [this](u32 reg, const Xbyak::Reg32& result) { |
| 547 | // Register 0 is supposed to always return 0. NOP is implemented as a store to the zero | 558 | // Register 0 is supposed to always return 0. NOP is implemented as a store to the zero |
| 548 | // register. | 559 | // register. |
| 549 | if (reg == 0) { | 560 | if (reg == 0) { |
| @@ -551,7 +562,7 @@ void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u3 | |||
| 551 | } | 562 | } |
| 552 | mov(dword[STATE + offsetof(JITState, registers) + reg * sizeof(u32)], result); | 563 | mov(dword[STATE + offsetof(JITState, registers) + reg * sizeof(u32)], result); |
| 553 | }; | 564 | }; |
| 554 | auto SetMethodAddress = [=](Xbyak::Reg32 reg) { mov(METHOD_ADDRESS, reg); }; | 565 | const auto SetMethodAddress = [this](const Xbyak::Reg32& reg) { mov(METHOD_ADDRESS, reg); }; |
| 555 | 566 | ||
| 556 | switch (operation) { | 567 | switch (operation) { |
| 557 | case Macro::ResultOperation::IgnoreAndFetch: | 568 | case Macro::ResultOperation::IgnoreAndFetch: |
diff --git a/src/video_core/macro/macro_jit_x64.h b/src/video_core/macro/macro_jit_x64.h index 51ec090b8..a180e7428 100644 --- a/src/video_core/macro/macro_jit_x64.h +++ b/src/video_core/macro/macro_jit_x64.h | |||
| @@ -76,6 +76,7 @@ private: | |||
| 76 | bool zero_reg_skip{}; | 76 | bool zero_reg_skip{}; |
| 77 | bool skip_dummy_addimmediate{}; | 77 | bool skip_dummy_addimmediate{}; |
| 78 | bool optimize_for_method_move{}; | 78 | bool optimize_for_method_move{}; |
| 79 | bool enable_asserts{}; | ||
| 79 | }; | 80 | }; |
| 80 | OptimizerState optimizer{}; | 81 | OptimizerState optimizer{}; |
| 81 | 82 | ||
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index dbee9f634..ff5505d12 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -210,10 +210,11 @@ bool MemoryManager::IsBlockContinuous(const GPUVAddr start, const std::size_t si | |||
| 210 | return range == inner_size; | 210 | return range == inner_size; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::size_t size) const { | 213 | void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, |
| 214 | const std::size_t size) const { | ||
| 214 | std::size_t remaining_size{size}; | 215 | std::size_t remaining_size{size}; |
| 215 | std::size_t page_index{src_addr >> page_bits}; | 216 | std::size_t page_index{gpu_src_addr >> page_bits}; |
| 216 | std::size_t page_offset{src_addr & page_mask}; | 217 | std::size_t page_offset{gpu_src_addr & page_mask}; |
| 217 | 218 | ||
| 218 | auto& memory = system.Memory(); | 219 | auto& memory = system.Memory(); |
| 219 | 220 | ||
| @@ -234,11 +235,11 @@ void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::s | |||
| 234 | } | 235 | } |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 237 | void MemoryManager::ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer, | 238 | void MemoryManager::ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer, |
| 238 | const std::size_t size) const { | 239 | const std::size_t size) const { |
| 239 | std::size_t remaining_size{size}; | 240 | std::size_t remaining_size{size}; |
| 240 | std::size_t page_index{src_addr >> page_bits}; | 241 | std::size_t page_index{gpu_src_addr >> page_bits}; |
| 241 | std::size_t page_offset{src_addr & page_mask}; | 242 | std::size_t page_offset{gpu_src_addr & page_mask}; |
| 242 | 243 | ||
| 243 | auto& memory = system.Memory(); | 244 | auto& memory = system.Memory(); |
| 244 | 245 | ||
| @@ -259,10 +260,11 @@ void MemoryManager::ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer, | |||
| 259 | } | 260 | } |
| 260 | } | 261 | } |
| 261 | 262 | ||
| 262 | void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const std::size_t size) { | 263 | void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, |
| 264 | const std::size_t size) { | ||
| 263 | std::size_t remaining_size{size}; | 265 | std::size_t remaining_size{size}; |
| 264 | std::size_t page_index{dest_addr >> page_bits}; | 266 | std::size_t page_index{gpu_dest_addr >> page_bits}; |
| 265 | std::size_t page_offset{dest_addr & page_mask}; | 267 | std::size_t page_offset{gpu_dest_addr & page_mask}; |
| 266 | 268 | ||
| 267 | auto& memory = system.Memory(); | 269 | auto& memory = system.Memory(); |
| 268 | 270 | ||
| @@ -283,11 +285,11 @@ void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const | |||
| 283 | } | 285 | } |
| 284 | } | 286 | } |
| 285 | 287 | ||
| 286 | void MemoryManager::WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer, | 288 | void MemoryManager::WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer, |
| 287 | const std::size_t size) { | 289 | const std::size_t size) { |
| 288 | std::size_t remaining_size{size}; | 290 | std::size_t remaining_size{size}; |
| 289 | std::size_t page_index{dest_addr >> page_bits}; | 291 | std::size_t page_index{gpu_dest_addr >> page_bits}; |
| 290 | std::size_t page_offset{dest_addr & page_mask}; | 292 | std::size_t page_offset{gpu_dest_addr & page_mask}; |
| 291 | 293 | ||
| 292 | auto& memory = system.Memory(); | 294 | auto& memory = system.Memory(); |
| 293 | 295 | ||
| @@ -306,16 +308,18 @@ void MemoryManager::WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer, | |||
| 306 | } | 308 | } |
| 307 | } | 309 | } |
| 308 | 310 | ||
| 309 | void MemoryManager::CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, const std::size_t size) { | 311 | void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, |
| 312 | const std::size_t size) { | ||
| 310 | std::vector<u8> tmp_buffer(size); | 313 | std::vector<u8> tmp_buffer(size); |
| 311 | ReadBlock(src_addr, tmp_buffer.data(), size); | 314 | ReadBlock(gpu_src_addr, tmp_buffer.data(), size); |
| 312 | WriteBlock(dest_addr, tmp_buffer.data(), size); | 315 | WriteBlock(gpu_dest_addr, tmp_buffer.data(), size); |
| 313 | } | 316 | } |
| 314 | 317 | ||
| 315 | void MemoryManager::CopyBlockUnsafe(GPUVAddr dest_addr, GPUVAddr src_addr, const std::size_t size) { | 318 | void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, |
| 319 | const std::size_t size) { | ||
| 316 | std::vector<u8> tmp_buffer(size); | 320 | std::vector<u8> tmp_buffer(size); |
| 317 | ReadBlockUnsafe(src_addr, tmp_buffer.data(), size); | 321 | ReadBlockUnsafe(gpu_src_addr, tmp_buffer.data(), size); |
| 318 | WriteBlockUnsafe(dest_addr, tmp_buffer.data(), size); | 322 | WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size); |
| 319 | } | 323 | } |
| 320 | 324 | ||
| 321 | bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) { | 325 | bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) { |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 0ddd52d5a..87658e87a 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -79,9 +79,9 @@ public: | |||
| 79 | * in the Host Memory counterpart. Note: This functions cause Host GPU Memory | 79 | * in the Host Memory counterpart. Note: This functions cause Host GPU Memory |
| 80 | * Flushes and Invalidations, respectively to each operation. | 80 | * Flushes and Invalidations, respectively to each operation. |
| 81 | */ | 81 | */ |
| 82 | void ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const; | 82 | void ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size) const; |
| 83 | void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size); | 83 | void WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size); |
| 84 | void CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size); | 84 | void CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size); |
| 85 | 85 | ||
| 86 | /** | 86 | /** |
| 87 | * ReadBlockUnsafe and WriteBlockUnsafe are special versions of ReadBlock and | 87 | * ReadBlockUnsafe and WriteBlockUnsafe are special versions of ReadBlock and |
| @@ -93,9 +93,9 @@ public: | |||
| 93 | * WriteBlockUnsafe instead of WriteBlock since it shouldn't invalidate the texture | 93 | * WriteBlockUnsafe instead of WriteBlock since it shouldn't invalidate the texture |
| 94 | * being flushed. | 94 | * being flushed. |
| 95 | */ | 95 | */ |
| 96 | void ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const; | 96 | void ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size) const; |
| 97 | void WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer, std::size_t size); | 97 | void WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size); |
| 98 | void CopyBlockUnsafe(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size); | 98 | void CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size); |
| 99 | 99 | ||
| 100 | /** | 100 | /** |
| 101 | * IsGranularRange checks if a gpu region can be simply read with a pointer | 101 | * IsGranularRange checks if a gpu region can be simply read with a pointer |
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index 2f75f8801..e12dab899 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h | |||
| @@ -220,8 +220,8 @@ private: | |||
| 220 | return cache_begin < addr_end && addr_begin < cache_end; | 220 | return cache_begin < addr_end && addr_begin < cache_end; |
| 221 | }; | 221 | }; |
| 222 | 222 | ||
| 223 | const u64 page_end = addr_end >> PAGE_SHIFT; | 223 | const u64 page_end = addr_end >> PAGE_BITS; |
| 224 | for (u64 page = addr_begin >> PAGE_SHIFT; page <= page_end; ++page) { | 224 | for (u64 page = addr_begin >> PAGE_BITS; page <= page_end; ++page) { |
| 225 | const auto& it = cached_queries.find(page); | 225 | const auto& it = cached_queries.find(page); |
| 226 | if (it == std::end(cached_queries)) { | 226 | if (it == std::end(cached_queries)) { |
| 227 | continue; | 227 | continue; |
| @@ -242,14 +242,14 @@ private: | |||
| 242 | /// Registers the passed parameters as cached and returns a pointer to the stored cached query. | 242 | /// Registers the passed parameters as cached and returns a pointer to the stored cached query. |
| 243 | CachedQuery* Register(VideoCore::QueryType type, VAddr cpu_addr, u8* host_ptr, bool timestamp) { | 243 | CachedQuery* Register(VideoCore::QueryType type, VAddr cpu_addr, u8* host_ptr, bool timestamp) { |
| 244 | rasterizer.UpdatePagesCachedCount(cpu_addr, CachedQuery::SizeInBytes(timestamp), 1); | 244 | rasterizer.UpdatePagesCachedCount(cpu_addr, CachedQuery::SizeInBytes(timestamp), 1); |
| 245 | const u64 page = static_cast<u64>(cpu_addr) >> PAGE_SHIFT; | 245 | const u64 page = static_cast<u64>(cpu_addr) >> PAGE_BITS; |
| 246 | return &cached_queries[page].emplace_back(static_cast<QueryCache&>(*this), type, cpu_addr, | 246 | return &cached_queries[page].emplace_back(static_cast<QueryCache&>(*this), type, cpu_addr, |
| 247 | host_ptr); | 247 | host_ptr); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | /// Tries to a get a cached query. Returns nullptr on failure. | 250 | /// Tries to a get a cached query. Returns nullptr on failure. |
| 251 | CachedQuery* TryGet(VAddr addr) { | 251 | CachedQuery* TryGet(VAddr addr) { |
| 252 | const u64 page = static_cast<u64>(addr) >> PAGE_SHIFT; | 252 | const u64 page = static_cast<u64>(addr) >> PAGE_BITS; |
| 253 | const auto it = cached_queries.find(page); | 253 | const auto it = cached_queries.find(page); |
| 254 | if (it == std::end(cached_queries)) { | 254 | if (it == std::end(cached_queries)) { |
| 255 | return nullptr; | 255 | return nullptr; |
| @@ -268,7 +268,7 @@ private: | |||
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | static constexpr std::uintptr_t PAGE_SIZE = 4096; | 270 | static constexpr std::uintptr_t PAGE_SIZE = 4096; |
| 271 | static constexpr unsigned PAGE_SHIFT = 12; | 271 | static constexpr unsigned PAGE_BITS = 12; |
| 272 | 272 | ||
| 273 | Core::System& system; | 273 | Core::System& system; |
| 274 | VideoCore::RasterizerInterface& rasterizer; | 274 | VideoCore::RasterizerInterface& rasterizer; |
diff --git a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp index 1e96b0310..eb5158407 100644 --- a/src/video_core/renderer_opengl/gl_arb_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_arb_decompiler.cpp | |||
| @@ -281,14 +281,14 @@ private: | |||
| 281 | 281 | ||
| 282 | template <const std::string_view& op> | 282 | template <const std::string_view& op> |
| 283 | std::string Unary(Operation operation) { | 283 | std::string Unary(Operation operation) { |
| 284 | const std::string temporary = AllocTemporary(); | 284 | std::string temporary = AllocTemporary(); |
| 285 | AddLine("{}{} {}, {};", op, Modifiers(operation), temporary, Visit(operation[0])); | 285 | AddLine("{}{} {}, {};", op, Modifiers(operation), temporary, Visit(operation[0])); |
| 286 | return temporary; | 286 | return temporary; |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | template <const std::string_view& op> | 289 | template <const std::string_view& op> |
| 290 | std::string Binary(Operation operation) { | 290 | std::string Binary(Operation operation) { |
| 291 | const std::string temporary = AllocTemporary(); | 291 | std::string temporary = AllocTemporary(); |
| 292 | AddLine("{}{} {}, {}, {};", op, Modifiers(operation), temporary, Visit(operation[0]), | 292 | AddLine("{}{} {}, {}, {};", op, Modifiers(operation), temporary, Visit(operation[0]), |
| 293 | Visit(operation[1])); | 293 | Visit(operation[1])); |
| 294 | return temporary; | 294 | return temporary; |
| @@ -296,7 +296,7 @@ private: | |||
| 296 | 296 | ||
| 297 | template <const std::string_view& op> | 297 | template <const std::string_view& op> |
| 298 | std::string Trinary(Operation operation) { | 298 | std::string Trinary(Operation operation) { |
| 299 | const std::string temporary = AllocTemporary(); | 299 | std::string temporary = AllocTemporary(); |
| 300 | AddLine("{}{} {}, {}, {}, {};", op, Modifiers(operation), temporary, Visit(operation[0]), | 300 | AddLine("{}{} {}, {}, {}, {};", op, Modifiers(operation), temporary, Visit(operation[0]), |
| 301 | Visit(operation[1]), Visit(operation[2])); | 301 | Visit(operation[1]), Visit(operation[2])); |
| 302 | return temporary; | 302 | return temporary; |
| @@ -304,7 +304,7 @@ private: | |||
| 304 | 304 | ||
| 305 | template <const std::string_view& op, bool unordered> | 305 | template <const std::string_view& op, bool unordered> |
| 306 | std::string FloatComparison(Operation operation) { | 306 | std::string FloatComparison(Operation operation) { |
| 307 | const std::string temporary = AllocTemporary(); | 307 | std::string temporary = AllocTemporary(); |
| 308 | AddLine("TRUNC.U.CC RC.x, {};", Binary<op>(operation)); | 308 | AddLine("TRUNC.U.CC RC.x, {};", Binary<op>(operation)); |
| 309 | AddLine("MOV.S {}, 0;", temporary); | 309 | AddLine("MOV.S {}, 0;", temporary); |
| 310 | AddLine("MOV.S {} (NE.x), -1;", temporary); | 310 | AddLine("MOV.S {} (NE.x), -1;", temporary); |
| @@ -331,7 +331,7 @@ private: | |||
| 331 | 331 | ||
| 332 | template <const std::string_view& op, bool is_nan> | 332 | template <const std::string_view& op, bool is_nan> |
| 333 | std::string HalfComparison(Operation operation) { | 333 | std::string HalfComparison(Operation operation) { |
| 334 | const std::string tmp1 = AllocVectorTemporary(); | 334 | std::string tmp1 = AllocVectorTemporary(); |
| 335 | const std::string tmp2 = AllocVectorTemporary(); | 335 | const std::string tmp2 = AllocVectorTemporary(); |
| 336 | const std::string op_a = Visit(operation[0]); | 336 | const std::string op_a = Visit(operation[0]); |
| 337 | const std::string op_b = Visit(operation[1]); | 337 | const std::string op_b = Visit(operation[1]); |
| @@ -367,15 +367,14 @@ private: | |||
| 367 | AddLine("MOV.F {}.{}, {};", value, Swizzle(i), Visit(meta.values[i])); | 367 | AddLine("MOV.F {}.{}, {};", value, Swizzle(i), Visit(meta.values[i])); |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | const std::string result = coord; | 370 | AddLine("ATOMIM.{}.{} {}.x, {}, {}, image[{}], {};", op, type, coord, value, coord, |
| 371 | AddLine("ATOMIM.{}.{} {}.x, {}, {}, image[{}], {};", op, type, result, value, coord, | ||
| 372 | image_id, ImageType(meta.image.type)); | 371 | image_id, ImageType(meta.image.type)); |
| 373 | return fmt::format("{}.x", result); | 372 | return fmt::format("{}.x", coord); |
| 374 | } | 373 | } |
| 375 | 374 | ||
| 376 | template <const std::string_view& op, const std::string_view& type> | 375 | template <const std::string_view& op, const std::string_view& type> |
| 377 | std::string Atomic(Operation operation) { | 376 | std::string Atomic(Operation operation) { |
| 378 | const std::string temporary = AllocTemporary(); | 377 | std::string temporary = AllocTemporary(); |
| 379 | std::string address; | 378 | std::string address; |
| 380 | std::string_view opname; | 379 | std::string_view opname; |
| 381 | if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) { | 380 | if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) { |
| @@ -396,7 +395,7 @@ private: | |||
| 396 | 395 | ||
| 397 | template <char type> | 396 | template <char type> |
| 398 | std::string Negate(Operation operation) { | 397 | std::string Negate(Operation operation) { |
| 399 | const std::string temporary = AllocTemporary(); | 398 | std::string temporary = AllocTemporary(); |
| 400 | if constexpr (type == 'F') { | 399 | if constexpr (type == 'F') { |
| 401 | AddLine("MOV.F32 {}, -{};", temporary, Visit(operation[0])); | 400 | AddLine("MOV.F32 {}, -{};", temporary, Visit(operation[0])); |
| 402 | } else { | 401 | } else { |
| @@ -407,7 +406,7 @@ private: | |||
| 407 | 406 | ||
| 408 | template <char type> | 407 | template <char type> |
| 409 | std::string Absolute(Operation operation) { | 408 | std::string Absolute(Operation operation) { |
| 410 | const std::string temporary = AllocTemporary(); | 409 | std::string temporary = AllocTemporary(); |
| 411 | AddLine("MOV.{} {}, |{}|;", type, temporary, Visit(operation[0])); | 410 | AddLine("MOV.{} {}, |{}|;", type, temporary, Visit(operation[0])); |
| 412 | return temporary; | 411 | return temporary; |
| 413 | } | 412 | } |
| @@ -1156,20 +1155,20 @@ void ARBDecompiler::VisitAST(const ASTNode& node) { | |||
| 1156 | } | 1155 | } |
| 1157 | 1156 | ||
| 1158 | std::string ARBDecompiler::VisitExpression(const Expr& node) { | 1157 | std::string ARBDecompiler::VisitExpression(const Expr& node) { |
| 1159 | const std::string result = AllocTemporary(); | ||
| 1160 | if (const auto expr = std::get_if<ExprAnd>(&*node)) { | 1158 | if (const auto expr = std::get_if<ExprAnd>(&*node)) { |
| 1159 | std::string result = AllocTemporary(); | ||
| 1161 | AddLine("AND.U {}, {}, {};", result, VisitExpression(expr->operand1), | 1160 | AddLine("AND.U {}, {}, {};", result, VisitExpression(expr->operand1), |
| 1162 | VisitExpression(expr->operand2)); | 1161 | VisitExpression(expr->operand2)); |
| 1163 | return result; | 1162 | return result; |
| 1164 | } | 1163 | } |
| 1165 | if (const auto expr = std::get_if<ExprOr>(&*node)) { | 1164 | if (const auto expr = std::get_if<ExprOr>(&*node)) { |
| 1166 | const std::string result = AllocTemporary(); | 1165 | std::string result = AllocTemporary(); |
| 1167 | AddLine("OR.U {}, {}, {};", result, VisitExpression(expr->operand1), | 1166 | AddLine("OR.U {}, {}, {};", result, VisitExpression(expr->operand1), |
| 1168 | VisitExpression(expr->operand2)); | 1167 | VisitExpression(expr->operand2)); |
| 1169 | return result; | 1168 | return result; |
| 1170 | } | 1169 | } |
| 1171 | if (const auto expr = std::get_if<ExprNot>(&*node)) { | 1170 | if (const auto expr = std::get_if<ExprNot>(&*node)) { |
| 1172 | const std::string result = AllocTemporary(); | 1171 | std::string result = AllocTemporary(); |
| 1173 | AddLine("CMP.S {}, {}, 0, -1;", result, VisitExpression(expr->operand1)); | 1172 | AddLine("CMP.S {}, {}, 0, -1;", result, VisitExpression(expr->operand1)); |
| 1174 | return result; | 1173 | return result; |
| 1175 | } | 1174 | } |
| @@ -1186,7 +1185,7 @@ std::string ARBDecompiler::VisitExpression(const Expr& node) { | |||
| 1186 | return expr->value ? "0xffffffff" : "0"; | 1185 | return expr->value ? "0xffffffff" : "0"; |
| 1187 | } | 1186 | } |
| 1188 | if (const auto expr = std::get_if<ExprGprEqual>(&*node)) { | 1187 | if (const auto expr = std::get_if<ExprGprEqual>(&*node)) { |
| 1189 | const std::string result = AllocTemporary(); | 1188 | std::string result = AllocTemporary(); |
| 1190 | AddLine("SEQ.U {}, R{}.x, {};", result, expr->gpr, expr->value); | 1189 | AddLine("SEQ.U {}, R{}.x, {};", result, expr->gpr, expr->value); |
| 1191 | return result; | 1190 | return result; |
| 1192 | } | 1191 | } |
| @@ -1231,13 +1230,13 @@ std::string ARBDecompiler::Visit(const Node& node) { | |||
| 1231 | } | 1230 | } |
| 1232 | 1231 | ||
| 1233 | if (const auto immediate = std::get_if<ImmediateNode>(&*node)) { | 1232 | if (const auto immediate = std::get_if<ImmediateNode>(&*node)) { |
| 1234 | const std::string temporary = AllocTemporary(); | 1233 | std::string temporary = AllocTemporary(); |
| 1235 | AddLine("MOV.U {}, {};", temporary, immediate->GetValue()); | 1234 | AddLine("MOV.U {}, {};", temporary, immediate->GetValue()); |
| 1236 | return temporary; | 1235 | return temporary; |
| 1237 | } | 1236 | } |
| 1238 | 1237 | ||
| 1239 | if (const auto predicate = std::get_if<PredicateNode>(&*node)) { | 1238 | if (const auto predicate = std::get_if<PredicateNode>(&*node)) { |
| 1240 | const std::string temporary = AllocTemporary(); | 1239 | std::string temporary = AllocTemporary(); |
| 1241 | switch (const auto index = predicate->GetIndex(); index) { | 1240 | switch (const auto index = predicate->GetIndex(); index) { |
| 1242 | case Tegra::Shader::Pred::UnusedIndex: | 1241 | case Tegra::Shader::Pred::UnusedIndex: |
| 1243 | AddLine("MOV.S {}, -1;", temporary); | 1242 | AddLine("MOV.S {}, -1;", temporary); |
| @@ -1333,13 +1332,13 @@ std::string ARBDecompiler::Visit(const Node& node) { | |||
| 1333 | } else { | 1332 | } else { |
| 1334 | offset_string = Visit(offset); | 1333 | offset_string = Visit(offset); |
| 1335 | } | 1334 | } |
| 1336 | const std::string temporary = AllocTemporary(); | 1335 | std::string temporary = AllocTemporary(); |
| 1337 | AddLine("LDC.F32 {}, cbuf{}[{}];", temporary, cbuf->GetIndex(), offset_string); | 1336 | AddLine("LDC.F32 {}, cbuf{}[{}];", temporary, cbuf->GetIndex(), offset_string); |
| 1338 | return temporary; | 1337 | return temporary; |
| 1339 | } | 1338 | } |
| 1340 | 1339 | ||
| 1341 | if (const auto gmem = std::get_if<GmemNode>(&*node)) { | 1340 | if (const auto gmem = std::get_if<GmemNode>(&*node)) { |
| 1342 | const std::string temporary = AllocTemporary(); | 1341 | std::string temporary = AllocTemporary(); |
| 1343 | AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), | 1342 | AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()), |
| 1344 | Visit(gmem->GetBaseAddress())); | 1343 | Visit(gmem->GetBaseAddress())); |
| 1345 | AddLine("LDB.U32 {}, {}[{}];", temporary, GlobalMemoryName(gmem->GetDescriptor()), | 1344 | AddLine("LDB.U32 {}, {}[{}];", temporary, GlobalMemoryName(gmem->GetDescriptor()), |
| @@ -1348,14 +1347,14 @@ std::string ARBDecompiler::Visit(const Node& node) { | |||
| 1348 | } | 1347 | } |
| 1349 | 1348 | ||
| 1350 | if (const auto lmem = std::get_if<LmemNode>(&*node)) { | 1349 | if (const auto lmem = std::get_if<LmemNode>(&*node)) { |
| 1351 | const std::string temporary = Visit(lmem->GetAddress()); | 1350 | std::string temporary = Visit(lmem->GetAddress()); |
| 1352 | AddLine("SHR.U {}, {}, 2;", temporary, temporary); | 1351 | AddLine("SHR.U {}, {}, 2;", temporary, temporary); |
| 1353 | AddLine("MOV.U {}, lmem[{}].x;", temporary, temporary); | 1352 | AddLine("MOV.U {}, lmem[{}].x;", temporary, temporary); |
| 1354 | return temporary; | 1353 | return temporary; |
| 1355 | } | 1354 | } |
| 1356 | 1355 | ||
| 1357 | if (const auto smem = std::get_if<SmemNode>(&*node)) { | 1356 | if (const auto smem = std::get_if<SmemNode>(&*node)) { |
| 1358 | const std::string temporary = Visit(smem->GetAddress()); | 1357 | std::string temporary = Visit(smem->GetAddress()); |
| 1359 | AddLine("LDS.U32 {}, shared_mem[{}];", temporary, temporary); | 1358 | AddLine("LDS.U32 {}, shared_mem[{}];", temporary, temporary); |
| 1360 | return temporary; | 1359 | return temporary; |
| 1361 | } | 1360 | } |
| @@ -1535,7 +1534,7 @@ std::string ARBDecompiler::Assign(Operation operation) { | |||
| 1535 | } | 1534 | } |
| 1536 | 1535 | ||
| 1537 | std::string ARBDecompiler::Select(Operation operation) { | 1536 | std::string ARBDecompiler::Select(Operation operation) { |
| 1538 | const std::string temporary = AllocTemporary(); | 1537 | std::string temporary = AllocTemporary(); |
| 1539 | AddLine("CMP.S {}, {}, {}, {};", temporary, Visit(operation[0]), Visit(operation[1]), | 1538 | AddLine("CMP.S {}, {}, {}, {};", temporary, Visit(operation[0]), Visit(operation[1]), |
| 1540 | Visit(operation[2])); | 1539 | Visit(operation[2])); |
| 1541 | return temporary; | 1540 | return temporary; |
| @@ -1545,12 +1544,12 @@ std::string ARBDecompiler::FClamp(Operation operation) { | |||
| 1545 | // 1.0f in hex, replace with std::bit_cast on C++20 | 1544 | // 1.0f in hex, replace with std::bit_cast on C++20 |
| 1546 | static constexpr u32 POSITIVE_ONE = 0x3f800000; | 1545 | static constexpr u32 POSITIVE_ONE = 0x3f800000; |
| 1547 | 1546 | ||
| 1548 | const std::string temporary = AllocTemporary(); | 1547 | std::string temporary = AllocTemporary(); |
| 1549 | const Node& value = operation[0]; | 1548 | const Node& value = operation[0]; |
| 1550 | const Node& low = operation[1]; | 1549 | const Node& low = operation[1]; |
| 1551 | const Node& high = operation[2]; | 1550 | const Node& high = operation[2]; |
| 1552 | const auto imm_low = std::get_if<ImmediateNode>(&*low); | 1551 | const auto* const imm_low = std::get_if<ImmediateNode>(&*low); |
| 1553 | const auto imm_high = std::get_if<ImmediateNode>(&*high); | 1552 | const auto* const imm_high = std::get_if<ImmediateNode>(&*high); |
| 1554 | if (imm_low && imm_high && imm_low->GetValue() == 0 && imm_high->GetValue() == POSITIVE_ONE) { | 1553 | if (imm_low && imm_high && imm_low->GetValue() == 0 && imm_high->GetValue() == POSITIVE_ONE) { |
| 1555 | AddLine("MOV.F32.SAT {}, {};", temporary, Visit(value)); | 1554 | AddLine("MOV.F32.SAT {}, {};", temporary, Visit(value)); |
| 1556 | } else { | 1555 | } else { |
| @@ -1574,7 +1573,7 @@ std::string ARBDecompiler::FCastHalf1(Operation operation) { | |||
| 1574 | } | 1573 | } |
| 1575 | 1574 | ||
| 1576 | std::string ARBDecompiler::FSqrt(Operation operation) { | 1575 | std::string ARBDecompiler::FSqrt(Operation operation) { |
| 1577 | const std::string temporary = AllocTemporary(); | 1576 | std::string temporary = AllocTemporary(); |
| 1578 | AddLine("RSQ.F32 {}, {};", temporary, Visit(operation[0])); | 1577 | AddLine("RSQ.F32 {}, {};", temporary, Visit(operation[0])); |
| 1579 | AddLine("RCP.F32 {}, {};", temporary, temporary); | 1578 | AddLine("RCP.F32 {}, {};", temporary, temporary); |
| 1580 | return temporary; | 1579 | return temporary; |
| @@ -1588,7 +1587,7 @@ std::string ARBDecompiler::FSwizzleAdd(Operation operation) { | |||
| 1588 | AddLine("ADD.F {}.x, {}, {};", temporary, Visit(operation[0]), Visit(operation[1])); | 1587 | AddLine("ADD.F {}.x, {}, {};", temporary, Visit(operation[0]), Visit(operation[1])); |
| 1589 | return fmt::format("{}.x", temporary); | 1588 | return fmt::format("{}.x", temporary); |
| 1590 | } | 1589 | } |
| 1591 | const std::string lut = AllocVectorTemporary(); | 1590 | |
| 1592 | AddLine("AND.U {}.z, {}.threadid, 3;", temporary, StageInputName(stage)); | 1591 | AddLine("AND.U {}.z, {}.threadid, 3;", temporary, StageInputName(stage)); |
| 1593 | AddLine("SHL.U {}.z, {}.z, 1;", temporary, temporary); | 1592 | AddLine("SHL.U {}.z, {}.z, 1;", temporary, temporary); |
| 1594 | AddLine("SHR.U {}.z, {}, {}.z;", temporary, Visit(operation[2]), temporary); | 1593 | AddLine("SHR.U {}.z, {}, {}.z;", temporary, Visit(operation[2]), temporary); |
| @@ -1766,21 +1765,21 @@ std::string ARBDecompiler::LogicalAssign(Operation operation) { | |||
| 1766 | } | 1765 | } |
| 1767 | 1766 | ||
| 1768 | std::string ARBDecompiler::LogicalPick2(Operation operation) { | 1767 | std::string ARBDecompiler::LogicalPick2(Operation operation) { |
| 1769 | const std::string temporary = AllocTemporary(); | 1768 | std::string temporary = AllocTemporary(); |
| 1770 | const u32 index = std::get<ImmediateNode>(*operation[1]).GetValue(); | 1769 | const u32 index = std::get<ImmediateNode>(*operation[1]).GetValue(); |
| 1771 | AddLine("MOV.U {}, {}.{};", temporary, Visit(operation[0]), Swizzle(index)); | 1770 | AddLine("MOV.U {}, {}.{};", temporary, Visit(operation[0]), Swizzle(index)); |
| 1772 | return temporary; | 1771 | return temporary; |
| 1773 | } | 1772 | } |
| 1774 | 1773 | ||
| 1775 | std::string ARBDecompiler::LogicalAnd2(Operation operation) { | 1774 | std::string ARBDecompiler::LogicalAnd2(Operation operation) { |
| 1776 | const std::string temporary = AllocTemporary(); | 1775 | std::string temporary = AllocTemporary(); |
| 1777 | const std::string op = Visit(operation[0]); | 1776 | const std::string op = Visit(operation[0]); |
| 1778 | AddLine("AND.U {}, {}.x, {}.y;", temporary, op, op); | 1777 | AddLine("AND.U {}, {}.x, {}.y;", temporary, op, op); |
| 1779 | return temporary; | 1778 | return temporary; |
| 1780 | } | 1779 | } |
| 1781 | 1780 | ||
| 1782 | std::string ARBDecompiler::FloatOrdered(Operation operation) { | 1781 | std::string ARBDecompiler::FloatOrdered(Operation operation) { |
| 1783 | const std::string temporary = AllocTemporary(); | 1782 | std::string temporary = AllocTemporary(); |
| 1784 | AddLine("MOVC.F32 RC.x, {};", Visit(operation[0])); | 1783 | AddLine("MOVC.F32 RC.x, {};", Visit(operation[0])); |
| 1785 | AddLine("MOVC.F32 RC.y, {};", Visit(operation[1])); | 1784 | AddLine("MOVC.F32 RC.y, {};", Visit(operation[1])); |
| 1786 | AddLine("MOV.S {}, -1;", temporary); | 1785 | AddLine("MOV.S {}, -1;", temporary); |
| @@ -1790,7 +1789,7 @@ std::string ARBDecompiler::FloatOrdered(Operation operation) { | |||
| 1790 | } | 1789 | } |
| 1791 | 1790 | ||
| 1792 | std::string ARBDecompiler::FloatUnordered(Operation operation) { | 1791 | std::string ARBDecompiler::FloatUnordered(Operation operation) { |
| 1793 | const std::string temporary = AllocTemporary(); | 1792 | std::string temporary = AllocTemporary(); |
| 1794 | AddLine("MOVC.F32 RC.x, {};", Visit(operation[0])); | 1793 | AddLine("MOVC.F32 RC.x, {};", Visit(operation[0])); |
| 1795 | AddLine("MOVC.F32 RC.y, {};", Visit(operation[1])); | 1794 | AddLine("MOVC.F32 RC.y, {};", Visit(operation[1])); |
| 1796 | AddLine("MOV.S {}, 0;", temporary); | 1795 | AddLine("MOV.S {}, 0;", temporary); |
| @@ -1800,7 +1799,7 @@ std::string ARBDecompiler::FloatUnordered(Operation operation) { | |||
| 1800 | } | 1799 | } |
| 1801 | 1800 | ||
| 1802 | std::string ARBDecompiler::LogicalAddCarry(Operation operation) { | 1801 | std::string ARBDecompiler::LogicalAddCarry(Operation operation) { |
| 1803 | const std::string temporary = AllocTemporary(); | 1802 | std::string temporary = AllocTemporary(); |
| 1804 | AddLine("ADDC.U RC, {}, {};", Visit(operation[0]), Visit(operation[1])); | 1803 | AddLine("ADDC.U RC, {}, {};", Visit(operation[0]), Visit(operation[1])); |
| 1805 | AddLine("MOV.S {}, 0;", temporary); | 1804 | AddLine("MOV.S {}, 0;", temporary); |
| 1806 | AddLine("IF CF.x;"); | 1805 | AddLine("IF CF.x;"); |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index ad0577a4f..d9f7b4cc6 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -22,21 +22,46 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs; | |||
| 22 | 22 | ||
| 23 | MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128)); | 23 | MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128)); |
| 24 | 24 | ||
| 25 | Buffer::Buffer(VAddr cpu_addr, const std::size_t size) : VideoCommon::BufferBlock{cpu_addr, size} { | 25 | Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size) |
| 26 | : VideoCommon::BufferBlock{cpu_addr, size} { | ||
| 26 | gl_buffer.Create(); | 27 | gl_buffer.Create(); |
| 27 | glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); | 28 | glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); |
| 29 | if (device.HasVertexBufferUnifiedMemory()) { | ||
| 30 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE); | ||
| 31 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); | ||
| 32 | } | ||
| 28 | } | 33 | } |
| 29 | 34 | ||
| 30 | Buffer::~Buffer() = default; | 35 | Buffer::~Buffer() = default; |
| 31 | 36 | ||
| 37 | void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const { | ||
| 38 | glNamedBufferSubData(Handle(), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), | ||
| 39 | data); | ||
| 40 | } | ||
| 41 | |||
| 42 | void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const { | ||
| 43 | MICROPROFILE_SCOPE(OpenGL_Buffer_Download); | ||
| 44 | glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); | ||
| 45 | glGetNamedBufferSubData(Handle(), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), | ||
| 46 | data); | ||
| 47 | } | ||
| 48 | |||
| 49 | void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||
| 50 | std::size_t size) const { | ||
| 51 | glCopyNamedBufferSubData(src.Handle(), Handle(), static_cast<GLintptr>(src_offset), | ||
| 52 | static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size)); | ||
| 53 | } | ||
| 54 | |||
| 32 | OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, | 55 | OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, |
| 33 | const Device& device, std::size_t stream_size) | 56 | const Device& device_, std::size_t stream_size) |
| 34 | : GenericBufferCache{rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} { | 57 | : GenericBufferCache{rasterizer, system, |
| 58 | std::make_unique<OGLStreamBuffer>(device_, stream_size, true)}, | ||
| 59 | device{device_} { | ||
| 35 | if (!device.HasFastBufferSubData()) { | 60 | if (!device.HasFastBufferSubData()) { |
| 36 | return; | 61 | return; |
| 37 | } | 62 | } |
| 38 | 63 | ||
| 39 | static constexpr auto size = static_cast<GLsizeiptr>(Maxwell::MaxConstBufferSize); | 64 | static constexpr GLsizeiptr size = static_cast<GLsizeiptr>(Maxwell::MaxConstBufferSize); |
| 40 | glCreateBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs)); | 65 | glCreateBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs)); |
| 41 | for (const GLuint cbuf : cbufs) { | 66 | for (const GLuint cbuf : cbufs) { |
| 42 | glNamedBufferData(cbuf, size, nullptr, GL_STREAM_DRAW); | 67 | glNamedBufferData(cbuf, size, nullptr, GL_STREAM_DRAW); |
| @@ -48,39 +73,20 @@ OGLBufferCache::~OGLBufferCache() { | |||
| 48 | } | 73 | } |
| 49 | 74 | ||
| 50 | std::shared_ptr<Buffer> OGLBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | 75 | std::shared_ptr<Buffer> OGLBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { |
| 51 | return std::make_shared<Buffer>(cpu_addr, size); | 76 | return std::make_shared<Buffer>(device, cpu_addr, size); |
| 52 | } | 77 | } |
| 53 | 78 | ||
| 54 | GLuint OGLBufferCache::GetEmptyBuffer(std::size_t) { | 79 | OGLBufferCache::BufferInfo OGLBufferCache::GetEmptyBuffer(std::size_t) { |
| 55 | return 0; | 80 | return {0, 0, 0}; |
| 56 | } | ||
| 57 | |||
| 58 | void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 59 | const u8* data) { | ||
| 60 | glNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset), | ||
| 61 | static_cast<GLsizeiptr>(size), data); | ||
| 62 | } | ||
| 63 | |||
| 64 | void OGLBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 65 | u8* data) { | ||
| 66 | MICROPROFILE_SCOPE(OpenGL_Buffer_Download); | ||
| 67 | glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); | ||
| 68 | glGetNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset), | ||
| 69 | static_cast<GLsizeiptr>(size), data); | ||
| 70 | } | ||
| 71 | |||
| 72 | void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 73 | std::size_t dst_offset, std::size_t size) { | ||
| 74 | glCopyNamedBufferSubData(src.Handle(), dst.Handle(), static_cast<GLintptr>(src_offset), | ||
| 75 | static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size)); | ||
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, | 83 | OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, |
| 79 | std::size_t size) { | 84 | std::size_t size) { |
| 80 | DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); | 85 | DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); |
| 81 | const GLuint cbuf = cbufs[cbuf_cursor++]; | 86 | const GLuint cbuf = cbufs[cbuf_cursor++]; |
| 87 | |||
| 82 | glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer); | 88 | glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer); |
| 83 | return {cbuf, 0}; | 89 | return {cbuf, 0, 0}; |
| 84 | } | 90 | } |
| 85 | 91 | ||
| 86 | } // namespace OpenGL | 92 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index a49aaf9c4..59d95adbc 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -25,15 +25,27 @@ class RasterizerOpenGL; | |||
| 25 | 25 | ||
| 26 | class Buffer : public VideoCommon::BufferBlock { | 26 | class Buffer : public VideoCommon::BufferBlock { |
| 27 | public: | 27 | public: |
| 28 | explicit Buffer(VAddr cpu_addr, const std::size_t size); | 28 | explicit Buffer(const Device& device, VAddr cpu_addr, std::size_t size); |
| 29 | ~Buffer(); | 29 | ~Buffer(); |
| 30 | 30 | ||
| 31 | GLuint Handle() const { | 31 | void Upload(std::size_t offset, std::size_t size, const u8* data) const; |
| 32 | |||
| 33 | void Download(std::size_t offset, std::size_t size, u8* data) const; | ||
| 34 | |||
| 35 | void CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||
| 36 | std::size_t size) const; | ||
| 37 | |||
| 38 | GLuint Handle() const noexcept { | ||
| 32 | return gl_buffer.handle; | 39 | return gl_buffer.handle; |
| 33 | } | 40 | } |
| 34 | 41 | ||
| 42 | u64 Address() const noexcept { | ||
| 43 | return gpu_address; | ||
| 44 | } | ||
| 45 | |||
| 35 | private: | 46 | private: |
| 36 | OGLBuffer gl_buffer; | 47 | OGLBuffer gl_buffer; |
| 48 | u64 gpu_address = 0; | ||
| 37 | }; | 49 | }; |
| 38 | 50 | ||
| 39 | using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>; | 51 | using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>; |
| @@ -43,7 +55,7 @@ public: | |||
| 43 | const Device& device, std::size_t stream_size); | 55 | const Device& device, std::size_t stream_size); |
| 44 | ~OGLBufferCache(); | 56 | ~OGLBufferCache(); |
| 45 | 57 | ||
| 46 | GLuint GetEmptyBuffer(std::size_t) override; | 58 | BufferInfo GetEmptyBuffer(std::size_t) override; |
| 47 | 59 | ||
| 48 | void Acquire() noexcept { | 60 | void Acquire() noexcept { |
| 49 | cbuf_cursor = 0; | 61 | cbuf_cursor = 0; |
| @@ -52,22 +64,16 @@ public: | |||
| 52 | protected: | 64 | protected: |
| 53 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; | 65 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; |
| 54 | 66 | ||
| 55 | void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 56 | const u8* data) override; | ||
| 57 | |||
| 58 | void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 59 | u8* data) override; | ||
| 60 | |||
| 61 | void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 62 | std::size_t dst_offset, std::size_t size) override; | ||
| 63 | |||
| 64 | BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override; | 67 | BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override; |
| 65 | 68 | ||
| 66 | private: | 69 | private: |
| 70 | static constexpr std::size_t NUM_CBUFS = Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers * | ||
| 71 | Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram; | ||
| 72 | |||
| 73 | const Device& device; | ||
| 74 | |||
| 67 | std::size_t cbuf_cursor = 0; | 75 | std::size_t cbuf_cursor = 0; |
| 68 | std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers * | 76 | std::array<GLuint, NUM_CBUFS> cbufs{}; |
| 69 | Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram> | ||
| 70 | cbufs; | ||
| 71 | }; | 77 | }; |
| 72 | 78 | ||
| 73 | } // namespace OpenGL | 79 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index b31d604e4..b6b6659c1 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -178,7 +178,7 @@ bool IsASTCSupported() { | |||
| 178 | for (const GLenum format : formats) { | 178 | for (const GLenum format : formats) { |
| 179 | for (const GLenum support : required_support) { | 179 | for (const GLenum support : required_support) { |
| 180 | GLint value; | 180 | GLint value; |
| 181 | glGetInternalformativ(GL_TEXTURE_2D, format, support, 1, &value); | 181 | glGetInternalformativ(target, format, support, 1, &value); |
| 182 | if (value != GL_FULL_SUPPORT) { | 182 | if (value != GL_FULL_SUPPORT) { |
| 183 | return false; | 183 | return false; |
| 184 | } | 184 | } |
| @@ -188,16 +188,32 @@ bool IsASTCSupported() { | |||
| 188 | return true; | 188 | return true; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | /// @brief Returns true when a GL_RENDERER is a Turing GPU | ||
| 192 | /// @param renderer GL_RENDERER string | ||
| 193 | bool IsTuring(std::string_view renderer) { | ||
| 194 | static constexpr std::array<std::string_view, 12> TURING_GPUS = { | ||
| 195 | "GTX 1650", "GTX 1660", "RTX 2060", "RTX 2070", | ||
| 196 | "RTX 2080", "TITAN RTX", "Quadro RTX 3000", "Quadro RTX 4000", | ||
| 197 | "Quadro RTX 5000", "Quadro RTX 6000", "Quadro RTX 8000", "Tesla T4", | ||
| 198 | }; | ||
| 199 | return std::any_of(TURING_GPUS.begin(), TURING_GPUS.end(), | ||
| 200 | [renderer](std::string_view candidate) { | ||
| 201 | return renderer.find(candidate) != std::string_view::npos; | ||
| 202 | }); | ||
| 203 | } | ||
| 204 | |||
| 191 | } // Anonymous namespace | 205 | } // Anonymous namespace |
| 192 | 206 | ||
| 193 | Device::Device() | 207 | Device::Device() |
| 194 | : max_uniform_buffers{BuildMaxUniformBuffers()}, base_bindings{BuildBaseBindings()} { | 208 | : max_uniform_buffers{BuildMaxUniformBuffers()}, base_bindings{BuildBaseBindings()} { |
| 195 | const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | 209 | const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); |
| 210 | const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); | ||
| 196 | const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); | 211 | const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); |
| 197 | const std::vector extensions = GetExtensions(); | 212 | const std::vector extensions = GetExtensions(); |
| 198 | 213 | ||
| 199 | const bool is_nvidia = vendor == "NVIDIA Corporation"; | 214 | const bool is_nvidia = vendor == "NVIDIA Corporation"; |
| 200 | const bool is_amd = vendor == "ATI Technologies Inc."; | 215 | const bool is_amd = vendor == "ATI Technologies Inc."; |
| 216 | const bool is_turing = is_nvidia && IsTuring(renderer); | ||
| 201 | 217 | ||
| 202 | bool disable_fast_buffer_sub_data = false; | 218 | bool disable_fast_buffer_sub_data = false; |
| 203 | if (is_nvidia && version == "4.6.0 NVIDIA 443.24") { | 219 | if (is_nvidia && version == "4.6.0 NVIDIA 443.24") { |
| @@ -216,12 +232,21 @@ Device::Device() | |||
| 216 | has_shader_ballot = GLAD_GL_ARB_shader_ballot; | 232 | has_shader_ballot = GLAD_GL_ARB_shader_ballot; |
| 217 | has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; | 233 | has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; |
| 218 | has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted"); | 234 | has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted"); |
| 235 | has_texture_shadow_lod = HasExtension(extensions, "GL_EXT_texture_shadow_lod"); | ||
| 219 | has_astc = IsASTCSupported(); | 236 | has_astc = IsASTCSupported(); |
| 220 | has_variable_aoffi = TestVariableAoffi(); | 237 | has_variable_aoffi = TestVariableAoffi(); |
| 221 | has_component_indexing_bug = is_amd; | 238 | has_component_indexing_bug = is_amd; |
| 222 | has_precise_bug = TestPreciseBug(); | 239 | has_precise_bug = TestPreciseBug(); |
| 223 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; | ||
| 224 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; | 240 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; |
| 241 | |||
| 242 | // At the moment of writing this, only Nvidia's driver optimizes BufferSubData on exclusive | ||
| 243 | // uniform buffers as "push constants" | ||
| 244 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; | ||
| 245 | |||
| 246 | // Nvidia's driver on Turing GPUs randomly crashes when the buffer is made resident, or on | ||
| 247 | // DeleteBuffers. Disable unified memory on these devices. | ||
| 248 | has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory && !is_turing; | ||
| 249 | |||
| 225 | use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 && | 250 | use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 && |
| 226 | GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && | 251 | GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && |
| 227 | GLAD_GL_NV_transform_feedback2; | 252 | GLAD_GL_NV_transform_feedback2; |
| @@ -245,6 +270,7 @@ Device::Device(std::nullptr_t) { | |||
| 245 | has_shader_ballot = true; | 270 | has_shader_ballot = true; |
| 246 | has_vertex_viewport_layer = true; | 271 | has_vertex_viewport_layer = true; |
| 247 | has_image_load_formatted = true; | 272 | has_image_load_formatted = true; |
| 273 | has_texture_shadow_lod = true; | ||
| 248 | has_variable_aoffi = true; | 274 | has_variable_aoffi = true; |
| 249 | } | 275 | } |
| 250 | 276 | ||
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index 145347943..e1d811966 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -68,6 +68,14 @@ public: | |||
| 68 | return has_image_load_formatted; | 68 | return has_image_load_formatted; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | bool HasTextureShadowLod() const { | ||
| 72 | return has_texture_shadow_lod; | ||
| 73 | } | ||
| 74 | |||
| 75 | bool HasVertexBufferUnifiedMemory() const { | ||
| 76 | return has_vertex_buffer_unified_memory; | ||
| 77 | } | ||
| 78 | |||
| 71 | bool HasASTC() const { | 79 | bool HasASTC() const { |
| 72 | return has_astc; | 80 | return has_astc; |
| 73 | } | 81 | } |
| @@ -110,6 +118,8 @@ private: | |||
| 110 | bool has_shader_ballot{}; | 118 | bool has_shader_ballot{}; |
| 111 | bool has_vertex_viewport_layer{}; | 119 | bool has_vertex_viewport_layer{}; |
| 112 | bool has_image_load_formatted{}; | 120 | bool has_image_load_formatted{}; |
| 121 | bool has_texture_shadow_lod{}; | ||
| 122 | bool has_vertex_buffer_unified_memory{}; | ||
| 113 | bool has_astc{}; | 123 | bool has_astc{}; |
| 114 | bool has_variable_aoffi{}; | 124 | bool has_variable_aoffi{}; |
| 115 | bool has_component_indexing_bug{}; | 125 | bool has_component_indexing_bug{}; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 2d6c11320..362457ffe 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -61,7 +61,8 @@ constexpr std::size_t NUM_CONST_BUFFERS_BYTES_PER_STAGE = | |||
| 61 | constexpr std::size_t TOTAL_CONST_BUFFER_BYTES = | 61 | constexpr std::size_t TOTAL_CONST_BUFFER_BYTES = |
| 62 | NUM_CONST_BUFFERS_BYTES_PER_STAGE * Maxwell::MaxShaderStage; | 62 | NUM_CONST_BUFFERS_BYTES_PER_STAGE * Maxwell::MaxShaderStage; |
| 63 | 63 | ||
| 64 | constexpr std::size_t NumSupportedVertexAttributes = 16; | 64 | constexpr std::size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16; |
| 65 | constexpr std::size_t NUM_SUPPORTED_VERTEX_BINDINGS = 16; | ||
| 65 | 66 | ||
| 66 | template <typename Engine, typename Entry> | 67 | template <typename Engine, typename Entry> |
| 67 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, | 68 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, |
| @@ -193,7 +194,7 @@ void RasterizerOpenGL::SetupVertexFormat() { | |||
| 193 | // avoid OpenGL errors. | 194 | // avoid OpenGL errors. |
| 194 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't | 195 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't |
| 195 | // assume every shader uses them all. | 196 | // assume every shader uses them all. |
| 196 | for (std::size_t index = 0; index < NumSupportedVertexAttributes; ++index) { | 197 | for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) { |
| 197 | if (!flags[Dirty::VertexFormat0 + index]) { | 198 | if (!flags[Dirty::VertexFormat0 + index]) { |
| 198 | continue; | 199 | continue; |
| 199 | } | 200 | } |
| @@ -231,9 +232,11 @@ void RasterizerOpenGL::SetupVertexBuffer() { | |||
| 231 | 232 | ||
| 232 | MICROPROFILE_SCOPE(OpenGL_VB); | 233 | MICROPROFILE_SCOPE(OpenGL_VB); |
| 233 | 234 | ||
| 235 | const bool use_unified_memory = device.HasVertexBufferUnifiedMemory(); | ||
| 236 | |||
| 234 | // Upload all guest vertex arrays sequentially to our buffer | 237 | // Upload all guest vertex arrays sequentially to our buffer |
| 235 | const auto& regs = gpu.regs; | 238 | const auto& regs = gpu.regs; |
| 236 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 239 | for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_BINDINGS; ++index) { |
| 237 | if (!flags[Dirty::VertexBuffer0 + index]) { | 240 | if (!flags[Dirty::VertexBuffer0 + index]) { |
| 238 | continue; | 241 | continue; |
| 239 | } | 242 | } |
| @@ -246,16 +249,25 @@ void RasterizerOpenGL::SetupVertexBuffer() { | |||
| 246 | 249 | ||
| 247 | const GPUVAddr start = vertex_array.StartAddress(); | 250 | const GPUVAddr start = vertex_array.StartAddress(); |
| 248 | const GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); | 251 | const GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); |
| 249 | |||
| 250 | ASSERT(end >= start); | 252 | ASSERT(end >= start); |
| 253 | |||
| 254 | const GLuint gl_index = static_cast<GLuint>(index); | ||
| 251 | const u64 size = end - start; | 255 | const u64 size = end - start; |
| 252 | if (size == 0) { | 256 | if (size == 0) { |
| 253 | glBindVertexBuffer(static_cast<GLuint>(index), 0, 0, vertex_array.stride); | 257 | glBindVertexBuffer(gl_index, 0, 0, vertex_array.stride); |
| 258 | if (use_unified_memory) { | ||
| 259 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, gl_index, 0, 0); | ||
| 260 | } | ||
| 254 | continue; | 261 | continue; |
| 255 | } | 262 | } |
| 256 | const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size); | 263 | const auto info = buffer_cache.UploadMemory(start, size); |
| 257 | glBindVertexBuffer(static_cast<GLuint>(index), vertex_buffer, vertex_buffer_offset, | 264 | if (use_unified_memory) { |
| 258 | vertex_array.stride); | 265 | glBindVertexBuffer(gl_index, 0, 0, vertex_array.stride); |
| 266 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, gl_index, | ||
| 267 | info.address + info.offset, size); | ||
| 268 | } else { | ||
| 269 | glBindVertexBuffer(gl_index, info.handle, info.offset, vertex_array.stride); | ||
| 270 | } | ||
| 259 | } | 271 | } |
| 260 | } | 272 | } |
| 261 | 273 | ||
| @@ -268,7 +280,7 @@ void RasterizerOpenGL::SetupVertexInstances() { | |||
| 268 | flags[Dirty::VertexInstances] = false; | 280 | flags[Dirty::VertexInstances] = false; |
| 269 | 281 | ||
| 270 | const auto& regs = gpu.regs; | 282 | const auto& regs = gpu.regs; |
| 271 | for (std::size_t index = 0; index < NumSupportedVertexAttributes; ++index) { | 283 | for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) { |
| 272 | if (!flags[Dirty::VertexInstance0 + index]) { | 284 | if (!flags[Dirty::VertexInstance0 + index]) { |
| 273 | continue; | 285 | continue; |
| 274 | } | 286 | } |
| @@ -285,9 +297,9 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() { | |||
| 285 | MICROPROFILE_SCOPE(OpenGL_Index); | 297 | MICROPROFILE_SCOPE(OpenGL_Index); |
| 286 | const auto& regs = system.GPU().Maxwell3D().regs; | 298 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 287 | const std::size_t size = CalculateIndexBufferSize(); | 299 | const std::size_t size = CalculateIndexBufferSize(); |
| 288 | const auto [buffer, offset] = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size); | 300 | const auto info = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size); |
| 289 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); | 301 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, info.handle); |
| 290 | return offset; | 302 | return info.offset; |
| 291 | } | 303 | } |
| 292 | 304 | ||
| 293 | void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | 305 | void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { |
| @@ -643,9 +655,9 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||
| 643 | if (!device.UseAssemblyShaders()) { | 655 | if (!device.UseAssemblyShaders()) { |
| 644 | MaxwellUniformData ubo; | 656 | MaxwellUniformData ubo; |
| 645 | ubo.SetFromRegs(gpu); | 657 | ubo.SetFromRegs(gpu); |
| 646 | const auto [buffer, offset] = | 658 | const auto info = |
| 647 | buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); | 659 | buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); |
| 648 | glBindBufferRange(GL_UNIFORM_BUFFER, EmulationUniformBlockBinding, buffer, offset, | 660 | glBindBufferRange(GL_UNIFORM_BUFFER, EmulationUniformBlockBinding, info.handle, info.offset, |
| 649 | static_cast<GLsizeiptr>(sizeof(ubo))); | 661 | static_cast<GLsizeiptr>(sizeof(ubo))); |
| 650 | } | 662 | } |
| 651 | 663 | ||
| @@ -956,8 +968,7 @@ void RasterizerOpenGL::SetupConstBuffer(GLenum stage, u32 binding, | |||
| 956 | if (device.UseAssemblyShaders()) { | 968 | if (device.UseAssemblyShaders()) { |
| 957 | glBindBufferRangeNV(stage, entry.GetIndex(), 0, 0, 0); | 969 | glBindBufferRangeNV(stage, entry.GetIndex(), 0, 0, 0); |
| 958 | } else { | 970 | } else { |
| 959 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, | 971 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, 0, 0, sizeof(float)); |
| 960 | buffer_cache.GetEmptyBuffer(sizeof(float)), 0, sizeof(float)); | ||
| 961 | } | 972 | } |
| 962 | return; | 973 | return; |
| 963 | } | 974 | } |
| @@ -970,24 +981,25 @@ void RasterizerOpenGL::SetupConstBuffer(GLenum stage, u32 binding, | |||
| 970 | 981 | ||
| 971 | const std::size_t alignment = use_unified ? 4 : device.GetUniformBufferAlignment(); | 982 | const std::size_t alignment = use_unified ? 4 : device.GetUniformBufferAlignment(); |
| 972 | const GPUVAddr gpu_addr = buffer.address; | 983 | const GPUVAddr gpu_addr = buffer.address; |
| 973 | auto [cbuf, offset] = buffer_cache.UploadMemory(gpu_addr, size, alignment, false, fast_upload); | 984 | auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, false, fast_upload); |
| 974 | 985 | ||
| 975 | if (device.UseAssemblyShaders()) { | 986 | if (device.UseAssemblyShaders()) { |
| 976 | UNIMPLEMENTED_IF(use_unified); | 987 | UNIMPLEMENTED_IF(use_unified); |
| 977 | if (offset != 0) { | 988 | if (info.offset != 0) { |
| 978 | const GLuint staging_cbuf = staging_cbufs[current_cbuf++]; | 989 | const GLuint staging_cbuf = staging_cbufs[current_cbuf++]; |
| 979 | glCopyNamedBufferSubData(cbuf, staging_cbuf, offset, 0, size); | 990 | glCopyNamedBufferSubData(info.handle, staging_cbuf, info.offset, 0, size); |
| 980 | cbuf = staging_cbuf; | 991 | info.handle = staging_cbuf; |
| 981 | offset = 0; | 992 | info.offset = 0; |
| 982 | } | 993 | } |
| 983 | glBindBufferRangeNV(stage, binding, cbuf, offset, size); | 994 | glBindBufferRangeNV(stage, binding, info.handle, info.offset, size); |
| 984 | return; | 995 | return; |
| 985 | } | 996 | } |
| 986 | 997 | ||
| 987 | if (use_unified) { | 998 | if (use_unified) { |
| 988 | glCopyNamedBufferSubData(cbuf, unified_uniform_buffer.handle, offset, unified_offset, size); | 999 | glCopyNamedBufferSubData(info.handle, unified_uniform_buffer.handle, info.offset, |
| 1000 | unified_offset, size); | ||
| 989 | } else { | 1001 | } else { |
| 990 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, cbuf, offset, size); | 1002 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, info.handle, info.offset, size); |
| 991 | } | 1003 | } |
| 992 | } | 1004 | } |
| 993 | 1005 | ||
| @@ -1023,9 +1035,8 @@ void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) { | |||
| 1023 | void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, | 1035 | void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, |
| 1024 | GPUVAddr gpu_addr, std::size_t size) { | 1036 | GPUVAddr gpu_addr, std::size_t size) { |
| 1025 | const auto alignment{device.GetShaderStorageBufferAlignment()}; | 1037 | const auto alignment{device.GetShaderStorageBufferAlignment()}; |
| 1026 | const auto [ssbo, buffer_offset] = | 1038 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); |
| 1027 | buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); | 1039 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset, |
| 1028 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, ssbo, buffer_offset, | ||
| 1029 | static_cast<GLsizeiptr>(size)); | 1040 | static_cast<GLsizeiptr>(size)); |
| 1030 | } | 1041 | } |
| 1031 | 1042 | ||
| @@ -1712,8 +1723,9 @@ void RasterizerOpenGL::EndTransformFeedback() { | |||
| 1712 | const GLuint handle = transform_feedback_buffers[index].handle; | 1723 | const GLuint handle = transform_feedback_buffers[index].handle; |
| 1713 | const GPUVAddr gpu_addr = binding.Address(); | 1724 | const GPUVAddr gpu_addr = binding.Address(); |
| 1714 | const std::size_t size = binding.buffer_size; | 1725 | const std::size_t size = binding.buffer_size; |
| 1715 | const auto [dest_buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); | 1726 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, 4, true); |
| 1716 | glCopyNamedBufferSubData(handle, dest_buffer, 0, offset, static_cast<GLsizeiptr>(size)); | 1727 | glCopyNamedBufferSubData(handle, info.handle, 0, info.offset, |
| 1728 | static_cast<GLsizeiptr>(size)); | ||
| 1717 | } | 1729 | } |
| 1718 | } | 1730 | } |
| 1719 | 1731 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 46e780a06..c6a3bf3a1 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -460,8 +460,9 @@ Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | |||
| 460 | const u8* host_ptr_b = memory_manager.GetPointer(address_b); | 460 | const u8* host_ptr_b = memory_manager.GetPointer(address_b); |
| 461 | code_b = GetShaderCode(memory_manager, address_b, host_ptr_b, false); | 461 | code_b = GetShaderCode(memory_manager, address_b, host_ptr_b, false); |
| 462 | } | 462 | } |
| 463 | const std::size_t code_size = code.size() * sizeof(u64); | ||
| 463 | 464 | ||
| 464 | const auto unique_identifier = GetUniqueIdentifier( | 465 | const u64 unique_identifier = GetUniqueIdentifier( |
| 465 | GetShaderType(program), program == Maxwell::ShaderProgram::VertexA, code, code_b); | 466 | GetShaderType(program), program == Maxwell::ShaderProgram::VertexA, code, code_b); |
| 466 | 467 | ||
| 467 | const ShaderParameters params{system, disk_cache, device, | 468 | const ShaderParameters params{system, disk_cache, device, |
| @@ -477,7 +478,7 @@ Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | |||
| 477 | 478 | ||
| 478 | Shader* const result = shader.get(); | 479 | Shader* const result = shader.get(); |
| 479 | if (cpu_addr) { | 480 | if (cpu_addr) { |
| 480 | Register(std::move(shader), *cpu_addr, code.size() * sizeof(u64)); | 481 | Register(std::move(shader), *cpu_addr, code_size); |
| 481 | } else { | 482 | } else { |
| 482 | null_shader = std::move(shader); | 483 | null_shader = std::move(shader); |
| 483 | } | 484 | } |
| @@ -495,8 +496,9 @@ Shader* ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) { | |||
| 495 | 496 | ||
| 496 | const auto host_ptr{memory_manager.GetPointer(code_addr)}; | 497 | const auto host_ptr{memory_manager.GetPointer(code_addr)}; |
| 497 | // No kernel found, create a new one | 498 | // No kernel found, create a new one |
| 498 | auto code{GetShaderCode(memory_manager, code_addr, host_ptr, true)}; | 499 | ProgramCode code{GetShaderCode(memory_manager, code_addr, host_ptr, true)}; |
| 499 | const auto unique_identifier{GetUniqueIdentifier(ShaderType::Compute, false, code)}; | 500 | const std::size_t code_size{code.size() * sizeof(u64)}; |
| 501 | const u64 unique_identifier{GetUniqueIdentifier(ShaderType::Compute, false, code)}; | ||
| 500 | 502 | ||
| 501 | const ShaderParameters params{system, disk_cache, device, | 503 | const ShaderParameters params{system, disk_cache, device, |
| 502 | *cpu_addr, host_ptr, unique_identifier}; | 504 | *cpu_addr, host_ptr, unique_identifier}; |
| @@ -511,7 +513,7 @@ Shader* ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) { | |||
| 511 | 513 | ||
| 512 | Shader* const result = kernel.get(); | 514 | Shader* const result = kernel.get(); |
| 513 | if (cpu_addr) { | 515 | if (cpu_addr) { |
| 514 | Register(std::move(kernel), *cpu_addr, code.size() * sizeof(u64)); | 516 | Register(std::move(kernel), *cpu_addr, code_size); |
| 515 | } else { | 517 | } else { |
| 516 | null_kernel = std::move(kernel); | 518 | null_kernel = std::move(kernel); |
| 517 | } | 519 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 6848f1388..994aaeaf2 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -37,7 +37,6 @@ namespace OpenGL { | |||
| 37 | 37 | ||
| 38 | class Device; | 38 | class Device; |
| 39 | class RasterizerOpenGL; | 39 | class RasterizerOpenGL; |
| 40 | struct UnspecializedShader; | ||
| 41 | 40 | ||
| 42 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 41 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 43 | 42 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index d6e30b321..2c49aeaac 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -37,6 +37,7 @@ using Tegra::Shader::IpaMode; | |||
| 37 | using Tegra::Shader::IpaSampleMode; | 37 | using Tegra::Shader::IpaSampleMode; |
| 38 | using Tegra::Shader::PixelImap; | 38 | using Tegra::Shader::PixelImap; |
| 39 | using Tegra::Shader::Register; | 39 | using Tegra::Shader::Register; |
| 40 | using Tegra::Shader::TextureType; | ||
| 40 | using VideoCommon::Shader::BuildTransformFeedback; | 41 | using VideoCommon::Shader::BuildTransformFeedback; |
| 41 | using VideoCommon::Shader::Registry; | 42 | using VideoCommon::Shader::Registry; |
| 42 | 43 | ||
| @@ -526,6 +527,9 @@ private: | |||
| 526 | if (device.HasImageLoadFormatted()) { | 527 | if (device.HasImageLoadFormatted()) { |
| 527 | code.AddLine("#extension GL_EXT_shader_image_load_formatted : require"); | 528 | code.AddLine("#extension GL_EXT_shader_image_load_formatted : require"); |
| 528 | } | 529 | } |
| 530 | if (device.HasTextureShadowLod()) { | ||
| 531 | code.AddLine("#extension GL_EXT_texture_shadow_lod : require"); | ||
| 532 | } | ||
| 529 | if (device.HasWarpIntrinsics()) { | 533 | if (device.HasWarpIntrinsics()) { |
| 530 | code.AddLine("#extension GL_NV_gpu_shader5 : require"); | 534 | code.AddLine("#extension GL_NV_gpu_shader5 : require"); |
| 531 | code.AddLine("#extension GL_NV_shader_thread_group : require"); | 535 | code.AddLine("#extension GL_NV_shader_thread_group : require"); |
| @@ -909,13 +913,13 @@ private: | |||
| 909 | return "samplerBuffer"; | 913 | return "samplerBuffer"; |
| 910 | } | 914 | } |
| 911 | switch (sampler.type) { | 915 | switch (sampler.type) { |
| 912 | case Tegra::Shader::TextureType::Texture1D: | 916 | case TextureType::Texture1D: |
| 913 | return "sampler1D"; | 917 | return "sampler1D"; |
| 914 | case Tegra::Shader::TextureType::Texture2D: | 918 | case TextureType::Texture2D: |
| 915 | return "sampler2D"; | 919 | return "sampler2D"; |
| 916 | case Tegra::Shader::TextureType::Texture3D: | 920 | case TextureType::Texture3D: |
| 917 | return "sampler3D"; | 921 | return "sampler3D"; |
| 918 | case Tegra::Shader::TextureType::TextureCube: | 922 | case TextureType::TextureCube: |
| 919 | return "samplerCube"; | 923 | return "samplerCube"; |
| 920 | default: | 924 | default: |
| 921 | UNREACHABLE(); | 925 | UNREACHABLE(); |
| @@ -1380,8 +1384,19 @@ private: | |||
| 1380 | const std::size_t count = operation.GetOperandsCount(); | 1384 | const std::size_t count = operation.GetOperandsCount(); |
| 1381 | const bool has_array = meta->sampler.is_array; | 1385 | const bool has_array = meta->sampler.is_array; |
| 1382 | const bool has_shadow = meta->sampler.is_shadow; | 1386 | const bool has_shadow = meta->sampler.is_shadow; |
| 1387 | const bool workaround_lod_array_shadow_as_grad = | ||
| 1388 | !device.HasTextureShadowLod() && function_suffix == "Lod" && meta->sampler.is_shadow && | ||
| 1389 | ((meta->sampler.type == TextureType::Texture2D && meta->sampler.is_array) || | ||
| 1390 | meta->sampler.type == TextureType::TextureCube); | ||
| 1391 | |||
| 1392 | std::string expr = "texture"; | ||
| 1393 | |||
| 1394 | if (workaround_lod_array_shadow_as_grad) { | ||
| 1395 | expr += "Grad"; | ||
| 1396 | } else { | ||
| 1397 | expr += function_suffix; | ||
| 1398 | } | ||
| 1383 | 1399 | ||
| 1384 | std::string expr = "texture" + function_suffix; | ||
| 1385 | if (!meta->aoffi.empty()) { | 1400 | if (!meta->aoffi.empty()) { |
| 1386 | expr += "Offset"; | 1401 | expr += "Offset"; |
| 1387 | } else if (!meta->ptp.empty()) { | 1402 | } else if (!meta->ptp.empty()) { |
| @@ -1415,6 +1430,16 @@ private: | |||
| 1415 | expr += ')'; | 1430 | expr += ')'; |
| 1416 | } | 1431 | } |
| 1417 | 1432 | ||
| 1433 | if (workaround_lod_array_shadow_as_grad) { | ||
| 1434 | switch (meta->sampler.type) { | ||
| 1435 | case TextureType::Texture2D: | ||
| 1436 | return expr + ", vec2(0.0), vec2(0.0))"; | ||
| 1437 | case TextureType::TextureCube: | ||
| 1438 | return expr + ", vec3(0.0), vec3(0.0))"; | ||
| 1439 | } | ||
| 1440 | UNREACHABLE(); | ||
| 1441 | } | ||
| 1442 | |||
| 1418 | for (const auto& variant : extras) { | 1443 | for (const auto& variant : extras) { |
| 1419 | if (const auto argument = std::get_if<TextureArgument>(&variant)) { | 1444 | if (const auto argument = std::get_if<TextureArgument>(&variant)) { |
| 1420 | expr += GenerateTextureArgument(*argument); | 1445 | expr += GenerateTextureArgument(*argument); |
| @@ -2041,8 +2066,19 @@ private: | |||
| 2041 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); | 2066 | const auto meta = std::get_if<MetaTexture>(&operation.GetMeta()); |
| 2042 | ASSERT(meta); | 2067 | ASSERT(meta); |
| 2043 | 2068 | ||
| 2044 | std::string expr = GenerateTexture( | 2069 | std::string expr{}; |
| 2045 | operation, "Lod", {TextureArgument{Type::Float, meta->lod}, TextureOffset{}}); | 2070 | |
| 2071 | if (!device.HasTextureShadowLod() && meta->sampler.is_shadow && | ||
| 2072 | ((meta->sampler.type == TextureType::Texture2D && meta->sampler.is_array) || | ||
| 2073 | meta->sampler.type == TextureType::TextureCube)) { | ||
| 2074 | LOG_ERROR(Render_OpenGL, | ||
| 2075 | "Device lacks GL_EXT_texture_shadow_lod, using textureGrad as a workaround"); | ||
| 2076 | expr = GenerateTexture(operation, "Lod", {}); | ||
| 2077 | } else { | ||
| 2078 | expr = GenerateTexture(operation, "Lod", | ||
| 2079 | {TextureArgument{Type::Float, meta->lod}, TextureOffset{}}); | ||
| 2080 | } | ||
| 2081 | |||
| 2046 | if (meta->sampler.is_shadow) { | 2082 | if (meta->sampler.is_shadow) { |
| 2047 | expr = "vec4(" + expr + ')'; | 2083 | expr = "vec4(" + expr + ')'; |
| 2048 | } | 2084 | } |
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp index 932a2f69e..3655ff629 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp +++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp | |||
| @@ -2,11 +2,13 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <deque> | 5 | #include <tuple> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | |||
| 7 | #include "common/alignment.h" | 8 | #include "common/alignment.h" |
| 8 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 9 | #include "common/microprofile.h" | 10 | #include "common/microprofile.h" |
| 11 | #include "video_core/renderer_opengl/gl_device.h" | ||
| 10 | #include "video_core/renderer_opengl/gl_stream_buffer.h" | 12 | #include "video_core/renderer_opengl/gl_stream_buffer.h" |
| 11 | 13 | ||
| 12 | MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning", | 14 | MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning", |
| @@ -14,8 +16,7 @@ MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning", | |||
| 14 | 16 | ||
| 15 | namespace OpenGL { | 17 | namespace OpenGL { |
| 16 | 18 | ||
| 17 | OGLStreamBuffer::OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent, | 19 | OGLStreamBuffer::OGLStreamBuffer(const Device& device, GLsizeiptr size, bool vertex_data_usage) |
| 18 | bool use_persistent) | ||
| 19 | : buffer_size(size) { | 20 | : buffer_size(size) { |
| 20 | gl_buffer.Create(); | 21 | gl_buffer.Create(); |
| 21 | 22 | ||
| @@ -29,23 +30,19 @@ OGLStreamBuffer::OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool p | |||
| 29 | allocate_size *= 2; | 30 | allocate_size *= 2; |
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | if (use_persistent) { | 33 | static constexpr GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT; |
| 33 | persistent = true; | 34 | glNamedBufferStorage(gl_buffer.handle, allocate_size, nullptr, flags); |
| 34 | coherent = prefer_coherent; | 35 | mapped_ptr = static_cast<u8*>( |
| 35 | const GLbitfield flags = | 36 | glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT)); |
| 36 | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); | 37 | |
| 37 | glNamedBufferStorage(gl_buffer.handle, allocate_size, nullptr, flags); | 38 | if (device.HasVertexBufferUnifiedMemory()) { |
| 38 | mapped_ptr = static_cast<u8*>(glMapNamedBufferRange( | 39 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY); |
| 39 | gl_buffer.handle, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT))); | 40 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); |
| 40 | } else { | ||
| 41 | glNamedBufferData(gl_buffer.handle, allocate_size, nullptr, GL_STREAM_DRAW); | ||
| 42 | } | 41 | } |
| 43 | } | 42 | } |
| 44 | 43 | ||
| 45 | OGLStreamBuffer::~OGLStreamBuffer() { | 44 | OGLStreamBuffer::~OGLStreamBuffer() { |
| 46 | if (persistent) { | 45 | glUnmapNamedBuffer(gl_buffer.handle); |
| 47 | glUnmapNamedBuffer(gl_buffer.handle); | ||
| 48 | } | ||
| 49 | gl_buffer.Release(); | 46 | gl_buffer.Release(); |
| 50 | } | 47 | } |
| 51 | 48 | ||
| @@ -60,36 +57,21 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a | |||
| 60 | 57 | ||
| 61 | bool invalidate = false; | 58 | bool invalidate = false; |
| 62 | if (buffer_pos + size > buffer_size) { | 59 | if (buffer_pos + size > buffer_size) { |
| 60 | MICROPROFILE_SCOPE(OpenGL_StreamBuffer); | ||
| 61 | glInvalidateBufferData(gl_buffer.handle); | ||
| 62 | |||
| 63 | buffer_pos = 0; | 63 | buffer_pos = 0; |
| 64 | invalidate = true; | 64 | invalidate = true; |
| 65 | |||
| 66 | if (persistent) { | ||
| 67 | glUnmapNamedBuffer(gl_buffer.handle); | ||
| 68 | } | ||
| 69 | } | 65 | } |
| 70 | 66 | ||
| 71 | if (invalidate || !persistent) { | 67 | return std::make_tuple(mapped_ptr + buffer_pos, buffer_pos, invalidate); |
| 72 | MICROPROFILE_SCOPE(OpenGL_StreamBuffer); | ||
| 73 | GLbitfield flags = GL_MAP_WRITE_BIT | (persistent ? GL_MAP_PERSISTENT_BIT : 0) | | ||
| 74 | (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) | | ||
| 75 | (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT); | ||
| 76 | mapped_ptr = static_cast<u8*>( | ||
| 77 | glMapNamedBufferRange(gl_buffer.handle, buffer_pos, buffer_size - buffer_pos, flags)); | ||
| 78 | mapped_offset = buffer_pos; | ||
| 79 | } | ||
| 80 | |||
| 81 | return std::make_tuple(mapped_ptr + buffer_pos - mapped_offset, buffer_pos, invalidate); | ||
| 82 | } | 68 | } |
| 83 | 69 | ||
| 84 | void OGLStreamBuffer::Unmap(GLsizeiptr size) { | 70 | void OGLStreamBuffer::Unmap(GLsizeiptr size) { |
| 85 | ASSERT(size <= mapped_size); | 71 | ASSERT(size <= mapped_size); |
| 86 | 72 | ||
| 87 | if (!coherent && size > 0) { | 73 | if (size > 0) { |
| 88 | glFlushMappedNamedBufferRange(gl_buffer.handle, buffer_pos - mapped_offset, size); | 74 | glFlushMappedNamedBufferRange(gl_buffer.handle, buffer_pos, size); |
| 89 | } | ||
| 90 | |||
| 91 | if (!persistent) { | ||
| 92 | glUnmapNamedBuffer(gl_buffer.handle); | ||
| 93 | } | 75 | } |
| 94 | 76 | ||
| 95 | buffer_pos += size; | 77 | buffer_pos += size; |
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h index 866da3594..307a67113 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.h +++ b/src/video_core/renderer_opengl/gl_stream_buffer.h | |||
| @@ -11,10 +11,11 @@ | |||
| 11 | 11 | ||
| 12 | namespace OpenGL { | 12 | namespace OpenGL { |
| 13 | 13 | ||
| 14 | class Device; | ||
| 15 | |||
| 14 | class OGLStreamBuffer : private NonCopyable { | 16 | class OGLStreamBuffer : private NonCopyable { |
| 15 | public: | 17 | public: |
| 16 | explicit OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent = false, | 18 | explicit OGLStreamBuffer(const Device& device, GLsizeiptr size, bool vertex_data_usage); |
| 17 | bool use_persistent = true); | ||
| 18 | ~OGLStreamBuffer(); | 19 | ~OGLStreamBuffer(); |
| 19 | 20 | ||
| 20 | /* | 21 | /* |
| @@ -33,19 +34,20 @@ public: | |||
| 33 | return gl_buffer.handle; | 34 | return gl_buffer.handle; |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | GLsizeiptr Size() const { | 37 | u64 Address() const { |
| 38 | return gpu_address; | ||
| 39 | } | ||
| 40 | |||
| 41 | GLsizeiptr Size() const noexcept { | ||
| 37 | return buffer_size; | 42 | return buffer_size; |
| 38 | } | 43 | } |
| 39 | 44 | ||
| 40 | private: | 45 | private: |
| 41 | OGLBuffer gl_buffer; | 46 | OGLBuffer gl_buffer; |
| 42 | 47 | ||
| 43 | bool coherent = false; | 48 | GLuint64EXT gpu_address = 0; |
| 44 | bool persistent = false; | ||
| 45 | |||
| 46 | GLintptr buffer_pos = 0; | 49 | GLintptr buffer_pos = 0; |
| 47 | GLsizeiptr buffer_size = 0; | 50 | GLsizeiptr buffer_size = 0; |
| 48 | GLintptr mapped_offset = 0; | ||
| 49 | GLsizeiptr mapped_size = 0; | 51 | GLsizeiptr mapped_size = 0; |
| 50 | u8* mapped_ptr = nullptr; | 52 | u8* mapped_ptr = nullptr; |
| 51 | }; | 53 | }; |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index 994ae98eb..35e329240 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -46,10 +46,8 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 46 | return GL_UNSIGNED_INT; | 46 | return GL_UNSIGNED_INT; |
| 47 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: | 47 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: |
| 48 | return GL_UNSIGNED_INT_2_10_10_10_REV; | 48 | return GL_UNSIGNED_INT_2_10_10_10_REV; |
| 49 | default: | ||
| 50 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | ||
| 51 | return {}; | ||
| 52 | } | 49 | } |
| 50 | break; | ||
| 53 | case Maxwell::VertexAttribute::Type::SignedInt: | 51 | case Maxwell::VertexAttribute::Type::SignedInt: |
| 54 | case Maxwell::VertexAttribute::Type::SignedNorm: | 52 | case Maxwell::VertexAttribute::Type::SignedNorm: |
| 55 | switch (attrib.size) { | 53 | switch (attrib.size) { |
| @@ -70,10 +68,8 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 70 | return GL_INT; | 68 | return GL_INT; |
| 71 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: | 69 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: |
| 72 | return GL_INT_2_10_10_10_REV; | 70 | return GL_INT_2_10_10_10_REV; |
| 73 | default: | ||
| 74 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | ||
| 75 | return {}; | ||
| 76 | } | 71 | } |
| 72 | break; | ||
| 77 | case Maxwell::VertexAttribute::Type::Float: | 73 | case Maxwell::VertexAttribute::Type::Float: |
| 78 | switch (attrib.size) { | 74 | switch (attrib.size) { |
| 79 | case Maxwell::VertexAttribute::Size::Size_16: | 75 | case Maxwell::VertexAttribute::Size::Size_16: |
| @@ -86,10 +82,8 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 86 | case Maxwell::VertexAttribute::Size::Size_32_32_32: | 82 | case Maxwell::VertexAttribute::Size::Size_32_32_32: |
| 87 | case Maxwell::VertexAttribute::Size::Size_32_32_32_32: | 83 | case Maxwell::VertexAttribute::Size::Size_32_32_32_32: |
| 88 | return GL_FLOAT; | 84 | return GL_FLOAT; |
| 89 | default: | ||
| 90 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | ||
| 91 | return {}; | ||
| 92 | } | 85 | } |
| 86 | break; | ||
| 93 | case Maxwell::VertexAttribute::Type::UnsignedScaled: | 87 | case Maxwell::VertexAttribute::Type::UnsignedScaled: |
| 94 | switch (attrib.size) { | 88 | switch (attrib.size) { |
| 95 | case Maxwell::VertexAttribute::Size::Size_8: | 89 | case Maxwell::VertexAttribute::Size::Size_8: |
| @@ -102,10 +96,8 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 102 | case Maxwell::VertexAttribute::Size::Size_16_16_16: | 96 | case Maxwell::VertexAttribute::Size::Size_16_16_16: |
| 103 | case Maxwell::VertexAttribute::Size::Size_16_16_16_16: | 97 | case Maxwell::VertexAttribute::Size::Size_16_16_16_16: |
| 104 | return GL_UNSIGNED_SHORT; | 98 | return GL_UNSIGNED_SHORT; |
| 105 | default: | ||
| 106 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | ||
| 107 | return {}; | ||
| 108 | } | 99 | } |
| 100 | break; | ||
| 109 | case Maxwell::VertexAttribute::Type::SignedScaled: | 101 | case Maxwell::VertexAttribute::Type::SignedScaled: |
| 110 | switch (attrib.size) { | 102 | switch (attrib.size) { |
| 111 | case Maxwell::VertexAttribute::Size::Size_8: | 103 | case Maxwell::VertexAttribute::Size::Size_8: |
| @@ -118,14 +110,12 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 118 | case Maxwell::VertexAttribute::Size::Size_16_16_16: | 110 | case Maxwell::VertexAttribute::Size::Size_16_16_16: |
| 119 | case Maxwell::VertexAttribute::Size::Size_16_16_16_16: | 111 | case Maxwell::VertexAttribute::Size::Size_16_16_16_16: |
| 120 | return GL_SHORT; | 112 | return GL_SHORT; |
| 121 | default: | ||
| 122 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | ||
| 123 | return {}; | ||
| 124 | } | 113 | } |
| 125 | default: | 114 | break; |
| 126 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex type={}", attrib.TypeString()); | ||
| 127 | return {}; | ||
| 128 | } | 115 | } |
| 116 | UNIMPLEMENTED_MSG("Unimplemented vertex type={} and size={}", attrib.TypeString(), | ||
| 117 | attrib.SizeString()); | ||
| 118 | return {}; | ||
| 129 | } | 119 | } |
| 130 | 120 | ||
| 131 | inline GLenum IndexFormat(Maxwell::IndexFormat index_format) { | 121 | inline GLenum IndexFormat(Maxwell::IndexFormat index_format) { |
| @@ -137,8 +127,7 @@ inline GLenum IndexFormat(Maxwell::IndexFormat index_format) { | |||
| 137 | case Maxwell::IndexFormat::UnsignedInt: | 127 | case Maxwell::IndexFormat::UnsignedInt: |
| 138 | return GL_UNSIGNED_INT; | 128 | return GL_UNSIGNED_INT; |
| 139 | } | 129 | } |
| 140 | LOG_CRITICAL(Render_OpenGL, "Unimplemented index_format={}", static_cast<u32>(index_format)); | 130 | UNREACHABLE_MSG("Invalid index_format={}", static_cast<u32>(index_format)); |
| 141 | UNREACHABLE(); | ||
| 142 | return {}; | 131 | return {}; |
| 143 | } | 132 | } |
| 144 | 133 | ||
| @@ -180,33 +169,32 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) { | |||
| 180 | } | 169 | } |
| 181 | 170 | ||
| 182 | inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode, | 171 | inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode, |
| 183 | Tegra::Texture::TextureMipmapFilter mip_filter_mode) { | 172 | Tegra::Texture::TextureMipmapFilter mipmap_filter_mode) { |
| 184 | switch (filter_mode) { | 173 | switch (filter_mode) { |
| 185 | case Tegra::Texture::TextureFilter::Linear: { | 174 | case Tegra::Texture::TextureFilter::Nearest: |
| 186 | switch (mip_filter_mode) { | 175 | switch (mipmap_filter_mode) { |
| 187 | case Tegra::Texture::TextureMipmapFilter::None: | 176 | case Tegra::Texture::TextureMipmapFilter::None: |
| 188 | return GL_LINEAR; | 177 | return GL_NEAREST; |
| 189 | case Tegra::Texture::TextureMipmapFilter::Nearest: | 178 | case Tegra::Texture::TextureMipmapFilter::Nearest: |
| 190 | return GL_LINEAR_MIPMAP_NEAREST; | 179 | return GL_NEAREST_MIPMAP_NEAREST; |
| 191 | case Tegra::Texture::TextureMipmapFilter::Linear: | 180 | case Tegra::Texture::TextureMipmapFilter::Linear: |
| 192 | return GL_LINEAR_MIPMAP_LINEAR; | 181 | return GL_NEAREST_MIPMAP_LINEAR; |
| 193 | } | 182 | } |
| 194 | break; | 183 | break; |
| 195 | } | 184 | case Tegra::Texture::TextureFilter::Linear: |
| 196 | case Tegra::Texture::TextureFilter::Nearest: { | 185 | switch (mipmap_filter_mode) { |
| 197 | switch (mip_filter_mode) { | ||
| 198 | case Tegra::Texture::TextureMipmapFilter::None: | 186 | case Tegra::Texture::TextureMipmapFilter::None: |
| 199 | return GL_NEAREST; | 187 | return GL_LINEAR; |
| 200 | case Tegra::Texture::TextureMipmapFilter::Nearest: | 188 | case Tegra::Texture::TextureMipmapFilter::Nearest: |
| 201 | return GL_NEAREST_MIPMAP_NEAREST; | 189 | return GL_LINEAR_MIPMAP_NEAREST; |
| 202 | case Tegra::Texture::TextureMipmapFilter::Linear: | 190 | case Tegra::Texture::TextureMipmapFilter::Linear: |
| 203 | return GL_NEAREST_MIPMAP_LINEAR; | 191 | return GL_LINEAR_MIPMAP_LINEAR; |
| 204 | } | 192 | } |
| 205 | break; | 193 | break; |
| 206 | } | 194 | } |
| 207 | } | 195 | UNREACHABLE_MSG("Invalid texture filter mode={} and mipmap filter mode={}", |
| 208 | LOG_ERROR(Render_OpenGL, "Unimplemented texture filter mode={}", static_cast<u32>(filter_mode)); | 196 | static_cast<u32>(filter_mode), static_cast<u32>(mipmap_filter_mode)); |
| 209 | return GL_LINEAR; | 197 | return GL_NEAREST; |
| 210 | } | 198 | } |
| 211 | 199 | ||
| 212 | inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { | 200 | inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { |
| @@ -229,10 +217,9 @@ inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) { | |||
| 229 | } else { | 217 | } else { |
| 230 | return GL_MIRROR_CLAMP_TO_EDGE; | 218 | return GL_MIRROR_CLAMP_TO_EDGE; |
| 231 | } | 219 | } |
| 232 | default: | ||
| 233 | LOG_ERROR(Render_OpenGL, "Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode)); | ||
| 234 | return GL_REPEAT; | ||
| 235 | } | 220 | } |
| 221 | UNIMPLEMENTED_MSG("Unimplemented texture wrap mode={}", static_cast<u32>(wrap_mode)); | ||
| 222 | return GL_REPEAT; | ||
| 236 | } | 223 | } |
| 237 | 224 | ||
| 238 | inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) { | 225 | inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) { |
| @@ -254,8 +241,7 @@ inline GLenum DepthCompareFunc(Tegra::Texture::DepthCompareFunc func) { | |||
| 254 | case Tegra::Texture::DepthCompareFunc::Always: | 241 | case Tegra::Texture::DepthCompareFunc::Always: |
| 255 | return GL_ALWAYS; | 242 | return GL_ALWAYS; |
| 256 | } | 243 | } |
| 257 | LOG_ERROR(Render_OpenGL, "Unimplemented texture depth compare function ={}", | 244 | UNIMPLEMENTED_MSG("Unimplemented texture depth compare function={}", static_cast<u32>(func)); |
| 258 | static_cast<u32>(func)); | ||
| 259 | return GL_GREATER; | 245 | return GL_GREATER; |
| 260 | } | 246 | } |
| 261 | 247 | ||
| @@ -277,7 +263,7 @@ inline GLenum BlendEquation(Maxwell::Blend::Equation equation) { | |||
| 277 | case Maxwell::Blend::Equation::MaxGL: | 263 | case Maxwell::Blend::Equation::MaxGL: |
| 278 | return GL_MAX; | 264 | return GL_MAX; |
| 279 | } | 265 | } |
| 280 | LOG_ERROR(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation)); | 266 | UNIMPLEMENTED_MSG("Unimplemented blend equation={}", static_cast<u32>(equation)); |
| 281 | return GL_FUNC_ADD; | 267 | return GL_FUNC_ADD; |
| 282 | } | 268 | } |
| 283 | 269 | ||
| @@ -341,7 +327,7 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) { | |||
| 341 | case Maxwell::Blend::Factor::OneMinusConstantAlphaGL: | 327 | case Maxwell::Blend::Factor::OneMinusConstantAlphaGL: |
| 342 | return GL_ONE_MINUS_CONSTANT_ALPHA; | 328 | return GL_ONE_MINUS_CONSTANT_ALPHA; |
| 343 | } | 329 | } |
| 344 | LOG_ERROR(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor)); | 330 | UNIMPLEMENTED_MSG("Unimplemented blend factor={}", static_cast<u32>(factor)); |
| 345 | return GL_ZERO; | 331 | return GL_ZERO; |
| 346 | } | 332 | } |
| 347 | 333 | ||
| @@ -361,7 +347,7 @@ inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) { | |||
| 361 | case Tegra::Texture::SwizzleSource::OneFloat: | 347 | case Tegra::Texture::SwizzleSource::OneFloat: |
| 362 | return GL_ONE; | 348 | return GL_ONE; |
| 363 | } | 349 | } |
| 364 | LOG_ERROR(Render_OpenGL, "Unimplemented swizzle source={}", static_cast<u32>(source)); | 350 | UNIMPLEMENTED_MSG("Unimplemented swizzle source={}", static_cast<u32>(source)); |
| 365 | return GL_ZERO; | 351 | return GL_ZERO; |
| 366 | } | 352 | } |
| 367 | 353 | ||
| @@ -392,7 +378,7 @@ inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) { | |||
| 392 | case Maxwell::ComparisonOp::AlwaysOld: | 378 | case Maxwell::ComparisonOp::AlwaysOld: |
| 393 | return GL_ALWAYS; | 379 | return GL_ALWAYS; |
| 394 | } | 380 | } |
| 395 | LOG_ERROR(Render_OpenGL, "Unimplemented comparison op={}", static_cast<u32>(comparison)); | 381 | UNIMPLEMENTED_MSG("Unimplemented comparison op={}", static_cast<u32>(comparison)); |
| 396 | return GL_ALWAYS; | 382 | return GL_ALWAYS; |
| 397 | } | 383 | } |
| 398 | 384 | ||
| @@ -423,7 +409,7 @@ inline GLenum StencilOp(Maxwell::StencilOp stencil) { | |||
| 423 | case Maxwell::StencilOp::DecrWrapOGL: | 409 | case Maxwell::StencilOp::DecrWrapOGL: |
| 424 | return GL_DECR_WRAP; | 410 | return GL_DECR_WRAP; |
| 425 | } | 411 | } |
| 426 | LOG_ERROR(Render_OpenGL, "Unimplemented stencil op={}", static_cast<u32>(stencil)); | 412 | UNIMPLEMENTED_MSG("Unimplemented stencil op={}", static_cast<u32>(stencil)); |
| 427 | return GL_KEEP; | 413 | return GL_KEEP; |
| 428 | } | 414 | } |
| 429 | 415 | ||
| @@ -434,7 +420,7 @@ inline GLenum FrontFace(Maxwell::FrontFace front_face) { | |||
| 434 | case Maxwell::FrontFace::CounterClockWise: | 420 | case Maxwell::FrontFace::CounterClockWise: |
| 435 | return GL_CCW; | 421 | return GL_CCW; |
| 436 | } | 422 | } |
| 437 | LOG_ERROR(Render_OpenGL, "Unimplemented front face cull={}", static_cast<u32>(front_face)); | 423 | UNIMPLEMENTED_MSG("Unimplemented front face cull={}", static_cast<u32>(front_face)); |
| 438 | return GL_CCW; | 424 | return GL_CCW; |
| 439 | } | 425 | } |
| 440 | 426 | ||
| @@ -447,7 +433,7 @@ inline GLenum CullFace(Maxwell::CullFace cull_face) { | |||
| 447 | case Maxwell::CullFace::FrontAndBack: | 433 | case Maxwell::CullFace::FrontAndBack: |
| 448 | return GL_FRONT_AND_BACK; | 434 | return GL_FRONT_AND_BACK; |
| 449 | } | 435 | } |
| 450 | LOG_ERROR(Render_OpenGL, "Unimplemented cull face={}", static_cast<u32>(cull_face)); | 436 | UNIMPLEMENTED_MSG("Unimplemented cull face={}", static_cast<u32>(cull_face)); |
| 451 | return GL_BACK; | 437 | return GL_BACK; |
| 452 | } | 438 | } |
| 453 | 439 | ||
| @@ -486,7 +472,7 @@ inline GLenum LogicOp(Maxwell::LogicOperation operation) { | |||
| 486 | case Maxwell::LogicOperation::Set: | 472 | case Maxwell::LogicOperation::Set: |
| 487 | return GL_SET; | 473 | return GL_SET; |
| 488 | } | 474 | } |
| 489 | LOG_ERROR(Render_OpenGL, "Unimplemented logic operation={}", static_cast<u32>(operation)); | 475 | UNIMPLEMENTED_MSG("Unimplemented logic operation={}", static_cast<u32>(operation)); |
| 490 | return GL_COPY; | 476 | return GL_COPY; |
| 491 | } | 477 | } |
| 492 | 478 | ||
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 6214fcbc3..c40adb6e7 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -488,6 +488,15 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 488 | 488 | ||
| 489 | // Clear screen to black | 489 | // Clear screen to black |
| 490 | LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); | 490 | LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); |
| 491 | |||
| 492 | // Enable unified vertex attributes and query vertex buffer address when the driver supports it | ||
| 493 | if (device.HasVertexBufferUnifiedMemory()) { | ||
| 494 | glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); | ||
| 495 | |||
| 496 | glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY); | ||
| 497 | glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, | ||
| 498 | &vertex_buffer_address); | ||
| 499 | } | ||
| 491 | } | 500 | } |
| 492 | 501 | ||
| 493 | void RendererOpenGL::AddTelemetryFields() { | 502 | void RendererOpenGL::AddTelemetryFields() { |
| @@ -656,7 +665,13 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 656 | offsetof(ScreenRectVertex, tex_coord)); | 665 | offsetof(ScreenRectVertex, tex_coord)); |
| 657 | glVertexAttribBinding(PositionLocation, 0); | 666 | glVertexAttribBinding(PositionLocation, 0); |
| 658 | glVertexAttribBinding(TexCoordLocation, 0); | 667 | glVertexAttribBinding(TexCoordLocation, 0); |
| 659 | glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); | 668 | if (device.HasVertexBufferUnifiedMemory()) { |
| 669 | glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex)); | ||
| 670 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address, | ||
| 671 | sizeof(vertices)); | ||
| 672 | } else { | ||
| 673 | glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); | ||
| 674 | } | ||
| 660 | 675 | ||
| 661 | glBindTextureUnit(0, screen_info.display_texture); | 676 | glBindTextureUnit(0, screen_info.display_texture); |
| 662 | glBindSampler(0, 0); | 677 | glBindSampler(0, 0); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 61bf507f4..8b18d32e6 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -107,6 +107,9 @@ private: | |||
| 107 | OGLPipeline pipeline; | 107 | OGLPipeline pipeline; |
| 108 | OGLFramebuffer screenshot_framebuffer; | 108 | OGLFramebuffer screenshot_framebuffer; |
| 109 | 109 | ||
| 110 | // GPU address of the vertex buffer | ||
| 111 | GLuint64EXT vertex_buffer_address = 0; | ||
| 112 | |||
| 110 | /// Display information for Switch screen | 113 | /// Display information for Switch screen |
| 111 | ScreenInfo screen_info; | 114 | ScreenInfo screen_info; |
| 112 | 115 | ||
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 62e950d31..1f2b6734b 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -21,29 +21,29 @@ namespace Sampler { | |||
| 21 | 21 | ||
| 22 | VkFilter Filter(Tegra::Texture::TextureFilter filter) { | 22 | VkFilter Filter(Tegra::Texture::TextureFilter filter) { |
| 23 | switch (filter) { | 23 | switch (filter) { |
| 24 | case Tegra::Texture::TextureFilter::Linear: | ||
| 25 | return VK_FILTER_LINEAR; | ||
| 26 | case Tegra::Texture::TextureFilter::Nearest: | 24 | case Tegra::Texture::TextureFilter::Nearest: |
| 27 | return VK_FILTER_NEAREST; | 25 | return VK_FILTER_NEAREST; |
| 26 | case Tegra::Texture::TextureFilter::Linear: | ||
| 27 | return VK_FILTER_LINEAR; | ||
| 28 | } | 28 | } |
| 29 | UNIMPLEMENTED_MSG("Unimplemented sampler filter={}", static_cast<u32>(filter)); | 29 | UNREACHABLE_MSG("Invalid sampler filter={}", static_cast<u32>(filter)); |
| 30 | return {}; | 30 | return {}; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | VkSamplerMipmapMode MipmapMode(Tegra::Texture::TextureMipmapFilter mipmap_filter) { | 33 | VkSamplerMipmapMode MipmapMode(Tegra::Texture::TextureMipmapFilter mipmap_filter) { |
| 34 | switch (mipmap_filter) { | 34 | switch (mipmap_filter) { |
| 35 | case Tegra::Texture::TextureMipmapFilter::None: | 35 | case Tegra::Texture::TextureMipmapFilter::None: |
| 36 | // TODO(Rodrigo): None seems to be mapped to OpenGL's mag and min filters without mipmapping | 36 | // There are no Vulkan filter modes that directly correspond to OpenGL minification filters |
| 37 | // (e.g. GL_NEAREST and GL_LINEAR). Vulkan doesn't have such a thing, find out if we have to | 37 | // of GL_LINEAR or GL_NEAREST, but they can be emulated using |
| 38 | // use an image view with a single mipmap level to emulate this. | 38 | // VK_SAMPLER_MIPMAP_MODE_NEAREST, minLod = 0, and maxLod = 0.25, and using minFilter = |
| 39 | return VK_SAMPLER_MIPMAP_MODE_LINEAR; | 39 | // VK_FILTER_LINEAR or minFilter = VK_FILTER_NEAREST, respectively. |
| 40 | ; | 40 | return VK_SAMPLER_MIPMAP_MODE_NEAREST; |
| 41 | case Tegra::Texture::TextureMipmapFilter::Linear: | ||
| 42 | return VK_SAMPLER_MIPMAP_MODE_LINEAR; | ||
| 43 | case Tegra::Texture::TextureMipmapFilter::Nearest: | 41 | case Tegra::Texture::TextureMipmapFilter::Nearest: |
| 44 | return VK_SAMPLER_MIPMAP_MODE_NEAREST; | 42 | return VK_SAMPLER_MIPMAP_MODE_NEAREST; |
| 43 | case Tegra::Texture::TextureMipmapFilter::Linear: | ||
| 44 | return VK_SAMPLER_MIPMAP_MODE_LINEAR; | ||
| 45 | } | 45 | } |
| 46 | UNIMPLEMENTED_MSG("Unimplemented sampler mipmap mode={}", static_cast<u32>(mipmap_filter)); | 46 | UNREACHABLE_MSG("Invalid sampler mipmap mode={}", static_cast<u32>(mipmap_filter)); |
| 47 | return {}; | 47 | return {}; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| @@ -78,10 +78,9 @@ VkSamplerAddressMode WrapMode(const VKDevice& device, Tegra::Texture::WrapMode w | |||
| 78 | case Tegra::Texture::WrapMode::MirrorOnceBorder: | 78 | case Tegra::Texture::WrapMode::MirrorOnceBorder: |
| 79 | UNIMPLEMENTED(); | 79 | UNIMPLEMENTED(); |
| 80 | return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; | 80 | return VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE; |
| 81 | default: | ||
| 82 | UNIMPLEMENTED_MSG("Unimplemented wrap mode={}", static_cast<u32>(wrap_mode)); | ||
| 83 | return {}; | ||
| 84 | } | 81 | } |
| 82 | UNIMPLEMENTED_MSG("Unimplemented wrap mode={}", static_cast<u32>(wrap_mode)); | ||
| 83 | return {}; | ||
| 85 | } | 84 | } |
| 86 | 85 | ||
| 87 | VkCompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compare_func) { | 86 | VkCompareOp DepthCompareFunction(Tegra::Texture::DepthCompareFunc depth_compare_func) { |
| @@ -288,10 +287,9 @@ VkPrimitiveTopology PrimitiveTopology([[maybe_unused]] const VKDevice& device, | |||
| 288 | return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; | 287 | return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; |
| 289 | case Maxwell::PrimitiveTopology::Patches: | 288 | case Maxwell::PrimitiveTopology::Patches: |
| 290 | return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; | 289 | return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST; |
| 291 | default: | ||
| 292 | UNIMPLEMENTED_MSG("Unimplemented topology={}", static_cast<u32>(topology)); | ||
| 293 | return {}; | ||
| 294 | } | 290 | } |
| 291 | UNIMPLEMENTED_MSG("Unimplemented topology={}", static_cast<u32>(topology)); | ||
| 292 | return {}; | ||
| 295 | } | 293 | } |
| 296 | 294 | ||
| 297 | VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttribute::Size size) { | 295 | VkFormat VertexFormat(Maxwell::VertexAttribute::Type type, Maxwell::VertexAttribute::Size size) { |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 59b441943..cd9673d1f 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <fmt/format.h> | 13 | #include <fmt/format.h> |
| 14 | 14 | ||
| 15 | #include "common/dynamic_library.h" | 15 | #include "common/dynamic_library.h" |
| 16 | #include "common/file_util.h" | ||
| 16 | #include "common/logging/log.h" | 17 | #include "common/logging/log.h" |
| 17 | #include "common/telemetry.h" | 18 | #include "common/telemetry.h" |
| 18 | #include "core/core.h" | 19 | #include "core/core.h" |
| @@ -76,7 +77,8 @@ Common::DynamicLibrary OpenVulkanLibrary() { | |||
| 76 | char* libvulkan_env = getenv("LIBVULKAN_PATH"); | 77 | char* libvulkan_env = getenv("LIBVULKAN_PATH"); |
| 77 | if (!libvulkan_env || !library.Open(libvulkan_env)) { | 78 | if (!libvulkan_env || !library.Open(libvulkan_env)) { |
| 78 | // Use the libvulkan.dylib from the application bundle. | 79 | // Use the libvulkan.dylib from the application bundle. |
| 79 | std::string filename = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; | 80 | const std::string filename = |
| 81 | FileUtil::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib"; | ||
| 80 | library.Open(filename.c_str()); | 82 | library.Open(filename.c_str()); |
| 81 | } | 83 | } |
| 82 | #else | 84 | #else |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 1fde38328..f10f96cd8 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -37,9 +37,9 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch | |||
| 37 | 37 | ||
| 38 | } // Anonymous namespace | 38 | } // Anonymous namespace |
| 39 | 39 | ||
| 40 | Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, | 40 | Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, |
| 41 | std::size_t size) | 41 | VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) |
| 42 | : VideoCommon::BufferBlock{cpu_addr, size} { | 42 | : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { |
| 43 | VkBufferCreateInfo ci; | 43 | VkBufferCreateInfo ci; |
| 44 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | 44 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
| 45 | ci.pNext = nullptr; | 45 | ci.pNext = nullptr; |
| @@ -56,40 +56,15 @@ Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cp | |||
| 56 | 56 | ||
| 57 | Buffer::~Buffer() = default; | 57 | Buffer::~Buffer() = default; |
| 58 | 58 | ||
| 59 | VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | 59 | void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const { |
| 60 | const VKDevice& device, VKMemoryManager& memory_manager, | ||
| 61 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||
| 62 | : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||
| 63 | CreateStreamBuffer(device, | ||
| 64 | scheduler)}, | ||
| 65 | device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||
| 66 | staging_pool} {} | ||
| 67 | |||
| 68 | VKBufferCache::~VKBufferCache() = default; | ||
| 69 | |||
| 70 | std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||
| 71 | return std::make_shared<Buffer>(device, memory_manager, cpu_addr, size); | ||
| 72 | } | ||
| 73 | |||
| 74 | VkBuffer VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||
| 75 | size = std::max(size, std::size_t(4)); | ||
| 76 | const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||
| 77 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 78 | scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||
| 79 | cmdbuf.FillBuffer(buffer, 0, size, 0); | ||
| 80 | }); | ||
| 81 | return *empty.handle; | ||
| 82 | } | ||
| 83 | |||
| 84 | void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 85 | const u8* data) { | ||
| 86 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); | 60 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); |
| 87 | std::memcpy(staging.commit->Map(size), data, size); | 61 | std::memcpy(staging.commit->Map(size), data, size); |
| 88 | 62 | ||
| 89 | scheduler.RequestOutsideRenderPassOperationContext(); | 63 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 90 | scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset, | 64 | |
| 91 | size](vk::CommandBuffer cmdbuf) { | 65 | const VkBuffer handle = Handle(); |
| 92 | cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size}); | 66 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { |
| 67 | cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); | ||
| 93 | 68 | ||
| 94 | VkBufferMemoryBarrier barrier; | 69 | VkBufferMemoryBarrier barrier; |
| 95 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 70 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
| @@ -98,7 +73,7 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | |||
| 98 | barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; | 73 | barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; |
| 99 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 74 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 100 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 75 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 101 | barrier.buffer = buffer; | 76 | barrier.buffer = handle; |
| 102 | barrier.offset = offset; | 77 | barrier.offset = offset; |
| 103 | barrier.size = size; | 78 | barrier.size = size; |
| 104 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, | 79 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, |
| @@ -106,12 +81,12 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | |||
| 106 | }); | 81 | }); |
| 107 | } | 82 | } |
| 108 | 83 | ||
| 109 | void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | 84 | void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const { |
| 110 | u8* data) { | ||
| 111 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); | 85 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); |
| 112 | scheduler.RequestOutsideRenderPassOperationContext(); | 86 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 113 | scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset, | 87 | |
| 114 | size](vk::CommandBuffer cmdbuf) { | 88 | const VkBuffer handle = Handle(); |
| 89 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { | ||
| 115 | VkBufferMemoryBarrier barrier; | 90 | VkBufferMemoryBarrier barrier; |
| 116 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 91 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
| 117 | barrier.pNext = nullptr; | 92 | barrier.pNext = nullptr; |
| @@ -119,7 +94,7 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | |||
| 119 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; | 94 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| 120 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 95 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 121 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 96 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 122 | barrier.buffer = buffer; | 97 | barrier.buffer = handle; |
| 123 | barrier.offset = offset; | 98 | barrier.offset = offset; |
| 124 | barrier.size = size; | 99 | barrier.size = size; |
| 125 | 100 | ||
| @@ -127,17 +102,19 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | |||
| 127 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | | 102 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | |
| 128 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | 103 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, |
| 129 | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); | 104 | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); |
| 130 | cmdbuf.CopyBuffer(buffer, staging, VkBufferCopy{offset, 0, size}); | 105 | cmdbuf.CopyBuffer(handle, staging, VkBufferCopy{offset, 0, size}); |
| 131 | }); | 106 | }); |
| 132 | scheduler.Finish(); | 107 | scheduler.Finish(); |
| 133 | 108 | ||
| 134 | std::memcpy(data, staging.commit->Map(size), size); | 109 | std::memcpy(data, staging.commit->Map(size), size); |
| 135 | } | 110 | } |
| 136 | 111 | ||
| 137 | void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | 112 | void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, |
| 138 | std::size_t dst_offset, std::size_t size) { | 113 | std::size_t size) const { |
| 139 | scheduler.RequestOutsideRenderPassOperationContext(); | 114 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 140 | scheduler.Record([src_buffer = src.Handle(), dst_buffer = dst.Handle(), src_offset, dst_offset, | 115 | |
| 116 | const VkBuffer dst_buffer = Handle(); | ||
| 117 | scheduler.Record([src_buffer = src.Handle(), dst_buffer, src_offset, dst_offset, | ||
| 141 | size](vk::CommandBuffer cmdbuf) { | 118 | size](vk::CommandBuffer cmdbuf) { |
| 142 | cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); | 119 | cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); |
| 143 | 120 | ||
| @@ -165,4 +142,30 @@ void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t | |||
| 165 | }); | 142 | }); |
| 166 | } | 143 | } |
| 167 | 144 | ||
| 145 | VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | ||
| 146 | const VKDevice& device, VKMemoryManager& memory_manager, | ||
| 147 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||
| 148 | : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||
| 149 | CreateStreamBuffer(device, | ||
| 150 | scheduler)}, | ||
| 151 | device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||
| 152 | staging_pool} {} | ||
| 153 | |||
| 154 | VKBufferCache::~VKBufferCache() = default; | ||
| 155 | |||
| 156 | std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||
| 157 | return std::make_shared<Buffer>(device, memory_manager, scheduler, staging_pool, cpu_addr, | ||
| 158 | size); | ||
| 159 | } | ||
| 160 | |||
| 161 | VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||
| 162 | size = std::max(size, std::size_t(4)); | ||
| 163 | const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||
| 164 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 165 | scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||
| 166 | cmdbuf.FillBuffer(buffer, 0, size, 0); | ||
| 167 | }); | ||
| 168 | return {*empty.handle, 0, 0}; | ||
| 169 | } | ||
| 170 | |||
| 168 | } // namespace Vulkan | 171 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 9ebbef835..3630aca77 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -25,15 +25,29 @@ class VKScheduler; | |||
| 25 | 25 | ||
| 26 | class Buffer final : public VideoCommon::BufferBlock { | 26 | class Buffer final : public VideoCommon::BufferBlock { |
| 27 | public: | 27 | public: |
| 28 | explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, | 28 | explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler, |
| 29 | std::size_t size); | 29 | VKStagingBufferPool& staging_pool, VAddr cpu_addr, std::size_t size); |
| 30 | ~Buffer(); | 30 | ~Buffer(); |
| 31 | 31 | ||
| 32 | void Upload(std::size_t offset, std::size_t size, const u8* data) const; | ||
| 33 | |||
| 34 | void Download(std::size_t offset, std::size_t size, u8* data) const; | ||
| 35 | |||
| 36 | void CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||
| 37 | std::size_t size) const; | ||
| 38 | |||
| 32 | VkBuffer Handle() const { | 39 | VkBuffer Handle() const { |
| 33 | return *buffer.handle; | 40 | return *buffer.handle; |
| 34 | } | 41 | } |
| 35 | 42 | ||
| 43 | u64 Address() const { | ||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 36 | private: | 47 | private: |
| 48 | VKScheduler& scheduler; | ||
| 49 | VKStagingBufferPool& staging_pool; | ||
| 50 | |||
| 37 | VKBuffer buffer; | 51 | VKBuffer buffer; |
| 38 | }; | 52 | }; |
| 39 | 53 | ||
| @@ -44,20 +58,11 @@ public: | |||
| 44 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool); | 58 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool); |
| 45 | ~VKBufferCache(); | 59 | ~VKBufferCache(); |
| 46 | 60 | ||
| 47 | VkBuffer GetEmptyBuffer(std::size_t size) override; | 61 | BufferInfo GetEmptyBuffer(std::size_t size) override; |
| 48 | 62 | ||
| 49 | protected: | 63 | protected: |
| 50 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; | 64 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; |
| 51 | 65 | ||
| 52 | void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 53 | const u8* data) override; | ||
| 54 | |||
| 55 | void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 56 | u8* data) override; | ||
| 57 | |||
| 58 | void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 59 | std::size_t dst_offset, std::size_t size) override; | ||
| 60 | |||
| 61 | private: | 66 | private: |
| 62 | const VKDevice& device; | 67 | const VKDevice& device; |
| 63 | VKMemoryManager& memory_manager; | 68 | VKMemoryManager& memory_manager; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 184b2238a..a8d94eac3 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -143,6 +143,49 @@ Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry | |||
| 143 | } | 143 | } |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /// @brief Determine if an attachment to be updated has to preserve contents | ||
| 147 | /// @param is_clear True when a clear is being executed | ||
| 148 | /// @param regs 3D registers | ||
| 149 | /// @return True when the contents have to be preserved | ||
| 150 | bool HasToPreserveColorContents(bool is_clear, const Maxwell& regs) { | ||
| 151 | if (!is_clear) { | ||
| 152 | return true; | ||
| 153 | } | ||
| 154 | // First we have to make sure all clear masks are enabled. | ||
| 155 | if (!regs.clear_buffers.R || !regs.clear_buffers.G || !regs.clear_buffers.B || | ||
| 156 | !regs.clear_buffers.A) { | ||
| 157 | return true; | ||
| 158 | } | ||
| 159 | // If scissors are disabled, the whole screen is cleared | ||
| 160 | if (!regs.clear_flags.scissor) { | ||
| 161 | return false; | ||
| 162 | } | ||
| 163 | // Then we have to confirm scissor testing clears the whole image | ||
| 164 | const std::size_t index = regs.clear_buffers.RT; | ||
| 165 | const auto& scissor = regs.scissor_test[0]; | ||
| 166 | return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.rt[index].width || | ||
| 167 | scissor.max_y < regs.rt[index].height; | ||
| 168 | } | ||
| 169 | |||
| 170 | /// @brief Determine if an attachment to be updated has to preserve contents | ||
| 171 | /// @param is_clear True when a clear is being executed | ||
| 172 | /// @param regs 3D registers | ||
| 173 | /// @return True when the contents have to be preserved | ||
| 174 | bool HasToPreserveDepthContents(bool is_clear, const Maxwell& regs) { | ||
| 175 | // If we are not clearing, the contents have to be preserved | ||
| 176 | if (!is_clear) { | ||
| 177 | return true; | ||
| 178 | } | ||
| 179 | // For depth stencil clears we only have to confirm scissor test covers the whole image | ||
| 180 | if (!regs.clear_flags.scissor) { | ||
| 181 | return false; | ||
| 182 | } | ||
| 183 | // Make sure the clear cover the whole image | ||
| 184 | const auto& scissor = regs.scissor_test[0]; | ||
| 185 | return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.zeta_width || | ||
| 186 | scissor.max_y < regs.zeta_height; | ||
| 187 | } | ||
| 188 | |||
| 146 | } // Anonymous namespace | 189 | } // Anonymous namespace |
| 147 | 190 | ||
| 148 | class BufferBindings final { | 191 | class BufferBindings final { |
| @@ -344,7 +387,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 344 | 387 | ||
| 345 | buffer_cache.Unmap(); | 388 | buffer_cache.Unmap(); |
| 346 | 389 | ||
| 347 | const Texceptions texceptions = UpdateAttachments(); | 390 | const Texceptions texceptions = UpdateAttachments(false); |
| 348 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); | 391 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); |
| 349 | 392 | ||
| 350 | key.renderpass_params = GetRenderPassParams(texceptions); | 393 | key.renderpass_params = GetRenderPassParams(texceptions); |
| @@ -400,7 +443,7 @@ void RasterizerVulkan::Clear() { | |||
| 400 | return; | 443 | return; |
| 401 | } | 444 | } |
| 402 | 445 | ||
| 403 | [[maybe_unused]] const auto texceptions = UpdateAttachments(); | 446 | [[maybe_unused]] const auto texceptions = UpdateAttachments(true); |
| 404 | DEBUG_ASSERT(texceptions.none()); | 447 | DEBUG_ASSERT(texceptions.none()); |
| 405 | SetupImageTransitions(0, color_attachments, zeta_attachment); | 448 | SetupImageTransitions(0, color_attachments, zeta_attachment); |
| 406 | 449 | ||
| @@ -677,9 +720,12 @@ void RasterizerVulkan::FlushWork() { | |||
| 677 | draw_counter = 0; | 720 | draw_counter = 0; |
| 678 | } | 721 | } |
| 679 | 722 | ||
| 680 | RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | 723 | RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments(bool is_clear) { |
| 681 | MICROPROFILE_SCOPE(Vulkan_RenderTargets); | 724 | MICROPROFILE_SCOPE(Vulkan_RenderTargets); |
| 682 | auto& dirty = system.GPU().Maxwell3D().dirty.flags; | 725 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 726 | auto& dirty = maxwell3d.dirty.flags; | ||
| 727 | auto& regs = maxwell3d.regs; | ||
| 728 | |||
| 683 | const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; | 729 | const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; |
| 684 | dirty[VideoCommon::Dirty::RenderTargets] = false; | 730 | dirty[VideoCommon::Dirty::RenderTargets] = false; |
| 685 | 731 | ||
| @@ -688,7 +734,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 688 | Texceptions texceptions; | 734 | Texceptions texceptions; |
| 689 | for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { | 735 | for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { |
| 690 | if (update_rendertargets) { | 736 | if (update_rendertargets) { |
| 691 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true); | 737 | const bool preserve_contents = HasToPreserveColorContents(is_clear, regs); |
| 738 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, preserve_contents); | ||
| 692 | } | 739 | } |
| 693 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { | 740 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { |
| 694 | texceptions[rt] = true; | 741 | texceptions[rt] = true; |
| @@ -696,7 +743,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 696 | } | 743 | } |
| 697 | 744 | ||
| 698 | if (update_rendertargets) { | 745 | if (update_rendertargets) { |
| 699 | zeta_attachment = texture_cache.GetDepthBufferSurface(true); | 746 | const bool preserve_contents = HasToPreserveDepthContents(is_clear, regs); |
| 747 | zeta_attachment = texture_cache.GetDepthBufferSurface(preserve_contents); | ||
| 700 | } | 748 | } |
| 701 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { | 749 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { |
| 702 | texceptions[ZETA_TEXCEPTION_INDEX] = true; | 750 | texceptions[ZETA_TEXCEPTION_INDEX] = true; |
| @@ -870,10 +918,10 @@ void RasterizerVulkan::BeginTransformFeedback() { | |||
| 870 | UNIMPLEMENTED_IF(binding.buffer_offset != 0); | 918 | UNIMPLEMENTED_IF(binding.buffer_offset != 0); |
| 871 | 919 | ||
| 872 | const GPUVAddr gpu_addr = binding.Address(); | 920 | const GPUVAddr gpu_addr = binding.Address(); |
| 873 | const std::size_t size = binding.buffer_size; | 921 | const VkDeviceSize size = static_cast<VkDeviceSize>(binding.buffer_size); |
| 874 | const auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); | 922 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, 4, true); |
| 875 | 923 | ||
| 876 | scheduler.Record([buffer = buffer, offset = offset, size](vk::CommandBuffer cmdbuf) { | 924 | scheduler.Record([buffer = info.handle, offset = info.offset, size](vk::CommandBuffer cmdbuf) { |
| 877 | cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size); | 925 | cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size); |
| 878 | cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); | 926 | cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); |
| 879 | }); | 927 | }); |
| @@ -925,8 +973,8 @@ void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex | |||
| 925 | buffer_bindings.AddVertexBinding(DefaultBuffer(), 0); | 973 | buffer_bindings.AddVertexBinding(DefaultBuffer(), 0); |
| 926 | continue; | 974 | continue; |
| 927 | } | 975 | } |
| 928 | const auto [buffer, offset] = buffer_cache.UploadMemory(start, size); | 976 | const auto info = buffer_cache.UploadMemory(start, size); |
| 929 | buffer_bindings.AddVertexBinding(buffer, offset); | 977 | buffer_bindings.AddVertexBinding(info.handle, info.offset); |
| 930 | } | 978 | } |
| 931 | } | 979 | } |
| 932 | 980 | ||
| @@ -948,7 +996,9 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar | |||
| 948 | break; | 996 | break; |
| 949 | } | 997 | } |
| 950 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); | 998 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); |
| 951 | auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); | 999 | const auto info = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); |
| 1000 | VkBuffer buffer = info.handle; | ||
| 1001 | u64 offset = info.offset; | ||
| 952 | std::tie(buffer, offset) = quad_indexed_pass.Assemble( | 1002 | std::tie(buffer, offset) = quad_indexed_pass.Assemble( |
| 953 | regs.index_array.format, params.num_vertices, params.base_vertex, buffer, offset); | 1003 | regs.index_array.format, params.num_vertices, params.base_vertex, buffer, offset); |
| 954 | 1004 | ||
| @@ -962,7 +1012,9 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar | |||
| 962 | break; | 1012 | break; |
| 963 | } | 1013 | } |
| 964 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); | 1014 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); |
| 965 | auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); | 1015 | const auto info = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); |
| 1016 | VkBuffer buffer = info.handle; | ||
| 1017 | u64 offset = info.offset; | ||
| 966 | 1018 | ||
| 967 | auto format = regs.index_array.format; | 1019 | auto format = regs.index_array.format; |
| 968 | const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte; | 1020 | const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte; |
| @@ -1109,10 +1161,9 @@ void RasterizerVulkan::SetupConstBuffer(const ConstBufferEntry& entry, | |||
| 1109 | Common::AlignUp(CalculateConstBufferSize(entry, buffer), 4 * sizeof(float)); | 1161 | Common::AlignUp(CalculateConstBufferSize(entry, buffer), 4 * sizeof(float)); |
| 1110 | ASSERT(size <= MaxConstbufferSize); | 1162 | ASSERT(size <= MaxConstbufferSize); |
| 1111 | 1163 | ||
| 1112 | const auto [buffer_handle, offset] = | 1164 | const auto info = |
| 1113 | buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); | 1165 | buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); |
| 1114 | 1166 | update_descriptor_queue.AddBuffer(info.handle, info.offset, size); | |
| 1115 | update_descriptor_queue.AddBuffer(buffer_handle, offset, size); | ||
| 1116 | } | 1167 | } |
| 1117 | 1168 | ||
| 1118 | void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address) { | 1169 | void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address) { |
| @@ -1126,14 +1177,14 @@ void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAdd | |||
| 1126 | // Note: Do *not* use DefaultBuffer() here, storage buffers can be written breaking the | 1177 | // Note: Do *not* use DefaultBuffer() here, storage buffers can be written breaking the |
| 1127 | // default buffer. | 1178 | // default buffer. |
| 1128 | static constexpr std::size_t dummy_size = 4; | 1179 | static constexpr std::size_t dummy_size = 4; |
| 1129 | const auto buffer = buffer_cache.GetEmptyBuffer(dummy_size); | 1180 | const auto info = buffer_cache.GetEmptyBuffer(dummy_size); |
| 1130 | update_descriptor_queue.AddBuffer(buffer, 0, dummy_size); | 1181 | update_descriptor_queue.AddBuffer(info.handle, info.offset, dummy_size); |
| 1131 | return; | 1182 | return; |
| 1132 | } | 1183 | } |
| 1133 | 1184 | ||
| 1134 | const auto [buffer, offset] = buffer_cache.UploadMemory( | 1185 | const auto info = buffer_cache.UploadMemory( |
| 1135 | actual_addr, size, device.GetStorageBufferAlignment(), entry.IsWritten()); | 1186 | actual_addr, size, device.GetStorageBufferAlignment(), entry.IsWritten()); |
| 1136 | update_descriptor_queue.AddBuffer(buffer, offset, size); | 1187 | update_descriptor_queue.AddBuffer(info.handle, info.offset, size); |
| 1137 | } | 1188 | } |
| 1138 | 1189 | ||
| 1139 | void RasterizerVulkan::SetupUniformTexels(const Tegra::Texture::TICEntry& tic, | 1190 | void RasterizerVulkan::SetupUniformTexels(const Tegra::Texture::TICEntry& tic, |
| @@ -1154,7 +1205,7 @@ void RasterizerVulkan::SetupTexture(const Tegra::Texture::FullTextureInfo& textu | |||
| 1154 | const auto sampler = sampler_cache.GetSampler(texture.tsc); | 1205 | const auto sampler = sampler_cache.GetSampler(texture.tsc); |
| 1155 | update_descriptor_queue.AddSampledImage(sampler, image_view); | 1206 | update_descriptor_queue.AddSampledImage(sampler, image_view); |
| 1156 | 1207 | ||
| 1157 | const auto image_layout = update_descriptor_queue.GetLastImageLayout(); | 1208 | VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout(); |
| 1158 | *image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; | 1209 | *image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; |
| 1159 | sampled_views.push_back(ImageView{std::move(view), image_layout}); | 1210 | sampled_views.push_back(ImageView{std::move(view), image_layout}); |
| 1160 | } | 1211 | } |
| @@ -1180,7 +1231,7 @@ void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const Ima | |||
| 1180 | view->GetImageView(tic.x_source, tic.y_source, tic.z_source, tic.w_source); | 1231 | view->GetImageView(tic.x_source, tic.y_source, tic.z_source, tic.w_source); |
| 1181 | update_descriptor_queue.AddImage(image_view); | 1232 | update_descriptor_queue.AddImage(image_view); |
| 1182 | 1233 | ||
| 1183 | const auto image_layout = update_descriptor_queue.GetLastImageLayout(); | 1234 | VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout(); |
| 1184 | *image_layout = VK_IMAGE_LAYOUT_GENERAL; | 1235 | *image_layout = VK_IMAGE_LAYOUT_GENERAL; |
| 1185 | image_views.push_back(ImageView{std::move(view), image_layout}); | 1236 | image_views.push_back(ImageView{std::move(view), image_layout}); |
| 1186 | } | 1237 | } |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index c8c187606..83e00e7e9 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -159,7 +159,10 @@ private: | |||
| 159 | 159 | ||
| 160 | void FlushWork(); | 160 | void FlushWork(); |
| 161 | 161 | ||
| 162 | Texceptions UpdateAttachments(); | 162 | /// @brief Updates the currently bound attachments |
| 163 | /// @param is_clear True when the framebuffer is updated as a clear | ||
| 164 | /// @return Bitfield of attachments being used as sampled textures | ||
| 165 | Texceptions UpdateAttachments(bool is_clear); | ||
| 163 | 166 | ||
| 164 | std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass); | 167 | std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass); |
| 165 | 168 | ||
diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp index e6f2fa553..616eacc36 100644 --- a/src/video_core/renderer_vulkan/vk_sampler_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_sampler_cache.cpp | |||
| @@ -9,6 +9,8 @@ | |||
| 9 | #include "video_core/renderer_vulkan/wrapper.h" | 9 | #include "video_core/renderer_vulkan/wrapper.h" |
| 10 | #include "video_core/textures/texture.h" | 10 | #include "video_core/textures/texture.h" |
| 11 | 11 | ||
| 12 | using Tegra::Texture::TextureMipmapFilter; | ||
| 13 | |||
| 12 | namespace Vulkan { | 14 | namespace Vulkan { |
| 13 | 15 | ||
| 14 | namespace { | 16 | namespace { |
| @@ -63,8 +65,8 @@ vk::Sampler VKSamplerCache::CreateSampler(const Tegra::Texture::TSCEntry& tsc) c | |||
| 63 | ci.maxAnisotropy = tsc.GetMaxAnisotropy(); | 65 | ci.maxAnisotropy = tsc.GetMaxAnisotropy(); |
| 64 | ci.compareEnable = tsc.depth_compare_enabled; | 66 | ci.compareEnable = tsc.depth_compare_enabled; |
| 65 | ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func); | 67 | ci.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func); |
| 66 | ci.minLod = tsc.GetMinLod(); | 68 | ci.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.GetMinLod(); |
| 67 | ci.maxLod = tsc.GetMaxLod(); | 69 | ci.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.GetMaxLod(); |
| 68 | ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color); | 70 | ci.borderColor = arbitrary_borders ? VK_BORDER_COLOR_INT_CUSTOM_EXT : ConvertBorderColor(color); |
| 69 | ci.unnormalizedCoordinates = VK_FALSE; | 71 | ci.unnormalizedCoordinates = VK_FALSE; |
| 70 | return device.GetLogical().CreateSampler(ci); | 72 | return device.GetLogical().CreateSampler(ci); |
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.h b/src/video_core/renderer_vulkan/vk_stream_buffer.h index c765c60a0..689f0d276 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.h +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.h | |||
| @@ -35,10 +35,14 @@ public: | |||
| 35 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. | 35 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. |
| 36 | void Unmap(u64 size); | 36 | void Unmap(u64 size); |
| 37 | 37 | ||
| 38 | VkBuffer Handle() const { | 38 | VkBuffer Handle() const noexcept { |
| 39 | return *buffer; | 39 | return *buffer; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | u64 Address() const noexcept { | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 42 | private: | 46 | private: |
| 43 | struct Watch final { | 47 | struct Watch final { |
| 44 | VKFenceWatch fence; | 48 | VKFenceWatch fence; |
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp index 681ecde98..351c048d2 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.cpp +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.cpp | |||
| @@ -24,35 +24,25 @@ void VKUpdateDescriptorQueue::TickFrame() { | |||
| 24 | } | 24 | } |
| 25 | 25 | ||
| 26 | void VKUpdateDescriptorQueue::Acquire() { | 26 | void VKUpdateDescriptorQueue::Acquire() { |
| 27 | entries.clear(); | 27 | // Minimum number of entries required. |
| 28 | } | 28 | // This is the maximum number of entries a single draw call migth use. |
| 29 | static constexpr std::size_t MIN_ENTRIES = 0x400; | ||
| 29 | 30 | ||
| 30 | void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template, | 31 | if (payload.size() + MIN_ENTRIES >= payload.max_size()) { |
| 31 | VkDescriptorSet set) { | ||
| 32 | if (payload.size() + entries.size() >= payload.max_size()) { | ||
| 33 | LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread"); | 32 | LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread"); |
| 34 | scheduler.WaitWorker(); | 33 | scheduler.WaitWorker(); |
| 35 | payload.clear(); | 34 | payload.clear(); |
| 36 | } | 35 | } |
| 36 | upload_start = &*payload.end(); | ||
| 37 | } | ||
| 37 | 38 | ||
| 38 | // TODO(Rodrigo): Rework to write the payload directly | 39 | void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template, |
| 39 | const auto payload_start = payload.data() + payload.size(); | 40 | VkDescriptorSet set) { |
| 40 | for (const auto& entry : entries) { | 41 | const void* const data = upload_start; |
| 41 | if (const auto image = std::get_if<VkDescriptorImageInfo>(&entry)) { | 42 | const vk::Device* const logical = &device.GetLogical(); |
| 42 | payload.push_back(*image); | 43 | scheduler.Record([data, logical, set, update_template](vk::CommandBuffer) { |
| 43 | } else if (const auto buffer = std::get_if<VkDescriptorBufferInfo>(&entry)) { | 44 | logical->UpdateDescriptorSet(set, update_template, data); |
| 44 | payload.push_back(*buffer); | 45 | }); |
| 45 | } else if (const auto texel = std::get_if<VkBufferView>(&entry)) { | ||
| 46 | payload.push_back(*texel); | ||
| 47 | } else { | ||
| 48 | UNREACHABLE(); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | scheduler.Record( | ||
| 53 | [payload_start, set, update_template, logical = &device.GetLogical()](vk::CommandBuffer) { | ||
| 54 | logical->UpdateDescriptorSet(set, update_template, payload_start); | ||
| 55 | }); | ||
| 56 | } | 46 | } |
| 57 | 47 | ||
| 58 | } // namespace Vulkan | 48 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_update_descriptor.h b/src/video_core/renderer_vulkan/vk_update_descriptor.h index cc7e3dff4..945320c72 100644 --- a/src/video_core/renderer_vulkan/vk_update_descriptor.h +++ b/src/video_core/renderer_vulkan/vk_update_descriptor.h | |||
| @@ -15,17 +15,13 @@ namespace Vulkan { | |||
| 15 | class VKDevice; | 15 | class VKDevice; |
| 16 | class VKScheduler; | 16 | class VKScheduler; |
| 17 | 17 | ||
| 18 | class DescriptorUpdateEntry { | 18 | struct DescriptorUpdateEntry { |
| 19 | public: | 19 | DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {} |
| 20 | explicit DescriptorUpdateEntry() {} | ||
| 21 | |||
| 22 | DescriptorUpdateEntry(VkDescriptorImageInfo image) : image{image} {} | ||
| 23 | 20 | ||
| 24 | DescriptorUpdateEntry(VkDescriptorBufferInfo buffer) : buffer{buffer} {} | 21 | DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {} |
| 25 | 22 | ||
| 26 | DescriptorUpdateEntry(VkBufferView texel_buffer) : texel_buffer{texel_buffer} {} | 23 | DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {} |
| 27 | 24 | ||
| 28 | private: | ||
| 29 | union { | 25 | union { |
| 30 | VkDescriptorImageInfo image; | 26 | VkDescriptorImageInfo image; |
| 31 | VkDescriptorBufferInfo buffer; | 27 | VkDescriptorBufferInfo buffer; |
| @@ -45,32 +41,34 @@ public: | |||
| 45 | void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set); | 41 | void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set); |
| 46 | 42 | ||
| 47 | void AddSampledImage(VkSampler sampler, VkImageView image_view) { | 43 | void AddSampledImage(VkSampler sampler, VkImageView image_view) { |
| 48 | entries.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}}); | 44 | payload.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}}); |
| 49 | } | 45 | } |
| 50 | 46 | ||
| 51 | void AddImage(VkImageView image_view) { | 47 | void AddImage(VkImageView image_view) { |
| 52 | entries.emplace_back(VkDescriptorImageInfo{{}, image_view, {}}); | 48 | payload.emplace_back(VkDescriptorImageInfo{{}, image_view, {}}); |
| 53 | } | 49 | } |
| 54 | 50 | ||
| 55 | void AddBuffer(VkBuffer buffer, u64 offset, std::size_t size) { | 51 | void AddBuffer(VkBuffer buffer, u64 offset, std::size_t size) { |
| 56 | entries.emplace_back(VkDescriptorBufferInfo{buffer, offset, size}); | 52 | payload.emplace_back(VkDescriptorBufferInfo{buffer, offset, size}); |
| 57 | } | 53 | } |
| 58 | 54 | ||
| 59 | void AddTexelBuffer(VkBufferView texel_buffer) { | 55 | void AddTexelBuffer(VkBufferView texel_buffer) { |
| 60 | entries.emplace_back(texel_buffer); | 56 | payload.emplace_back(texel_buffer); |
| 61 | } | 57 | } |
| 62 | 58 | ||
| 63 | VkImageLayout* GetLastImageLayout() { | 59 | VkImageLayout* LastImageLayout() { |
| 64 | return &std::get<VkDescriptorImageInfo>(entries.back()).imageLayout; | 60 | return &payload.back().image.imageLayout; |
| 65 | } | 61 | } |
| 66 | 62 | ||
| 67 | private: | 63 | const VkImageLayout* LastImageLayout() const { |
| 68 | using Variant = std::variant<VkDescriptorImageInfo, VkDescriptorBufferInfo, VkBufferView>; | 64 | return &payload.back().image.imageLayout; |
| 65 | } | ||
| 69 | 66 | ||
| 67 | private: | ||
| 70 | const VKDevice& device; | 68 | const VKDevice& device; |
| 71 | VKScheduler& scheduler; | 69 | VKScheduler& scheduler; |
| 72 | 70 | ||
| 73 | boost::container::static_vector<Variant, 0x400> entries; | 71 | const DescriptorUpdateEntry* upload_start = nullptr; |
| 74 | boost::container::static_vector<DescriptorUpdateEntry, 0x10000> payload; | 72 | boost::container::static_vector<DescriptorUpdateEntry, 0x10000> payload; |
| 75 | }; | 73 | }; |
| 76 | 74 | ||
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp index 2ce9b0626..42eff85d3 100644 --- a/src/video_core/renderer_vulkan/wrapper.cpp +++ b/src/video_core/renderer_vulkan/wrapper.cpp | |||
| @@ -725,8 +725,7 @@ bool PhysicalDevice::GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR s | |||
| 725 | return supported == VK_TRUE; | 725 | return supported == VK_TRUE; |
| 726 | } | 726 | } |
| 727 | 727 | ||
| 728 | VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const | 728 | VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const { |
| 729 | noexcept { | ||
| 730 | VkSurfaceCapabilitiesKHR capabilities; | 729 | VkSurfaceCapabilitiesKHR capabilities; |
| 731 | Check(dld->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &capabilities)); | 730 | Check(dld->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &capabilities)); |
| 732 | return capabilities; | 731 | return capabilities; |
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h index 98937a77a..da42ca88e 100644 --- a/src/video_core/renderer_vulkan/wrapper.h +++ b/src/video_core/renderer_vulkan/wrapper.h | |||
| @@ -779,7 +779,7 @@ public: | |||
| 779 | 779 | ||
| 780 | bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const; | 780 | bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const; |
| 781 | 781 | ||
| 782 | VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const noexcept; | 782 | VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const; |
| 783 | 783 | ||
| 784 | std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const; | 784 | std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const; |
| 785 | 785 | ||
diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp index 848e46874..b2e88fa20 100644 --- a/src/video_core/shader/decode/half_set.cpp +++ b/src/video_core/shader/decode/half_set.cpp | |||
| @@ -13,55 +13,101 @@ | |||
| 13 | 13 | ||
| 14 | namespace VideoCommon::Shader { | 14 | namespace VideoCommon::Shader { |
| 15 | 15 | ||
| 16 | using std::move; | ||
| 16 | using Tegra::Shader::Instruction; | 17 | using Tegra::Shader::Instruction; |
| 17 | using Tegra::Shader::OpCode; | 18 | using Tegra::Shader::OpCode; |
| 19 | using Tegra::Shader::PredCondition; | ||
| 18 | 20 | ||
| 19 | u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) { | 21 | u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) { |
| 20 | const Instruction instr = {program_code[pc]}; | 22 | const Instruction instr = {program_code[pc]}; |
| 21 | const auto opcode = OpCode::Decode(instr); | 23 | const auto opcode = OpCode::Decode(instr); |
| 22 | 24 | ||
| 23 | if (instr.hset2.ftz == 0) { | 25 | PredCondition cond; |
| 24 | LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); | 26 | bool bf; |
| 27 | bool ftz; | ||
| 28 | bool neg_a; | ||
| 29 | bool abs_a; | ||
| 30 | bool neg_b; | ||
| 31 | bool abs_b; | ||
| 32 | switch (opcode->get().GetId()) { | ||
| 33 | case OpCode::Id::HSET2_C: | ||
| 34 | case OpCode::Id::HSET2_IMM: | ||
| 35 | cond = instr.hsetp2.cbuf_and_imm.cond; | ||
| 36 | bf = instr.Bit(53); | ||
| 37 | ftz = instr.Bit(54); | ||
| 38 | neg_a = instr.Bit(43); | ||
| 39 | abs_a = instr.Bit(44); | ||
| 40 | neg_b = instr.Bit(56); | ||
| 41 | abs_b = instr.Bit(54); | ||
| 42 | break; | ||
| 43 | case OpCode::Id::HSET2_R: | ||
| 44 | cond = instr.hsetp2.reg.cond; | ||
| 45 | bf = instr.Bit(49); | ||
| 46 | ftz = instr.Bit(50); | ||
| 47 | neg_a = instr.Bit(43); | ||
| 48 | abs_a = instr.Bit(44); | ||
| 49 | neg_b = instr.Bit(31); | ||
| 50 | abs_b = instr.Bit(30); | ||
| 51 | break; | ||
| 52 | default: | ||
| 53 | UNREACHABLE(); | ||
| 25 | } | 54 | } |
| 26 | 55 | ||
| 27 | Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); | 56 | Node op_b = [this, instr, opcode] { |
| 28 | op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a); | ||
| 29 | |||
| 30 | Node op_b = [&]() { | ||
| 31 | switch (opcode->get().GetId()) { | 57 | switch (opcode->get().GetId()) { |
| 58 | case OpCode::Id::HSET2_C: | ||
| 59 | // Inform as unimplemented as this is not tested. | ||
| 60 | UNIMPLEMENTED_MSG("HSET2_C is not implemented"); | ||
| 61 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); | ||
| 32 | case OpCode::Id::HSET2_R: | 62 | case OpCode::Id::HSET2_R: |
| 33 | return GetRegister(instr.gpr20); | 63 | return GetRegister(instr.gpr20); |
| 64 | case OpCode::Id::HSET2_IMM: | ||
| 65 | return UnpackHalfImmediate(instr, true); | ||
| 34 | default: | 66 | default: |
| 35 | UNREACHABLE(); | 67 | UNREACHABLE(); |
| 36 | return Immediate(0); | 68 | return Node{}; |
| 37 | } | 69 | } |
| 38 | }(); | 70 | }(); |
| 39 | op_b = UnpackHalfFloat(op_b, instr.hset2.type_b); | ||
| 40 | op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b); | ||
| 41 | 71 | ||
| 42 | const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred); | 72 | if (!ftz) { |
| 73 | LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); | ||
| 74 | } | ||
| 75 | |||
| 76 | Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); | ||
| 77 | op_a = GetOperandAbsNegHalf(op_a, abs_a, neg_a); | ||
| 78 | |||
| 79 | switch (opcode->get().GetId()) { | ||
| 80 | case OpCode::Id::HSET2_R: | ||
| 81 | op_b = GetOperandAbsNegHalf(move(op_b), abs_b, neg_b); | ||
| 82 | [[fallthrough]]; | ||
| 83 | case OpCode::Id::HSET2_C: | ||
| 84 | op_b = UnpackHalfFloat(move(op_b), instr.hset2.type_b); | ||
| 85 | break; | ||
| 86 | default: | ||
| 87 | break; | ||
| 88 | } | ||
| 43 | 89 | ||
| 44 | const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, op_a, op_b); | 90 | Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred); |
| 91 | |||
| 92 | Node comparison_pair = GetPredicateComparisonHalf(cond, op_a, op_b); | ||
| 45 | 93 | ||
| 46 | const OperationCode combiner = GetPredicateCombiner(instr.hset2.op); | 94 | const OperationCode combiner = GetPredicateCombiner(instr.hset2.op); |
| 47 | 95 | ||
| 48 | // HSET2 operates on each half float in the pack. | 96 | // HSET2 operates on each half float in the pack. |
| 49 | std::array<Node, 2> values; | 97 | std::array<Node, 2> values; |
| 50 | for (u32 i = 0; i < 2; ++i) { | 98 | for (u32 i = 0; i < 2; ++i) { |
| 51 | const u32 raw_value = instr.hset2.bf ? 0x3c00 : 0xffff; | 99 | const u32 raw_value = bf ? 0x3c00 : 0xffff; |
| 52 | const Node true_value = Immediate(raw_value << (i * 16)); | 100 | Node true_value = Immediate(raw_value << (i * 16)); |
| 53 | const Node false_value = Immediate(0); | 101 | Node false_value = Immediate(0); |
| 54 | |||
| 55 | const Node comparison = | ||
| 56 | Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); | ||
| 57 | const Node predicate = Operation(combiner, comparison, second_pred); | ||
| 58 | 102 | ||
| 103 | Node comparison = Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); | ||
| 104 | Node predicate = Operation(combiner, comparison, second_pred); | ||
| 59 | values[i] = | 105 | values[i] = |
| 60 | Operation(OperationCode::Select, NO_PRECISE, predicate, true_value, false_value); | 106 | Operation(OperationCode::Select, predicate, move(true_value), move(false_value)); |
| 61 | } | 107 | } |
| 62 | 108 | ||
| 63 | const Node value = Operation(OperationCode::UBitwiseOr, NO_PRECISE, values[0], values[1]); | 109 | Node value = Operation(OperationCode::UBitwiseOr, values[0], values[1]); |
| 64 | SetRegister(bb, instr.gpr0, value); | 110 | SetRegister(bb, instr.gpr0, move(value)); |
| 65 | 111 | ||
| 66 | return pc; | 112 | return pc; |
| 67 | } | 113 | } |
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index 60b6ad72a..07778dc3e 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -97,6 +97,7 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor, | |||
| 97 | break; | 97 | break; |
| 98 | case TextureFormat::B5G6R5: | 98 | case TextureFormat::B5G6R5: |
| 99 | case TextureFormat::B6G5R5: | 99 | case TextureFormat::B6G5R5: |
| 100 | case TextureFormat::BF10GF11RF11: | ||
| 100 | if (component == 0) { | 101 | if (component == 0) { |
| 101 | return descriptor.b_type; | 102 | return descriptor.b_type; |
| 102 | } | 103 | } |
| @@ -119,7 +120,7 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor, | |||
| 119 | } | 120 | } |
| 120 | break; | 121 | break; |
| 121 | } | 122 | } |
| 122 | UNIMPLEMENTED_MSG("texture format not implement={}", format); | 123 | UNIMPLEMENTED_MSG("Texture format not implemented={}", format); |
| 123 | return ComponentType::FLOAT; | 124 | return ComponentType::FLOAT; |
| 124 | } | 125 | } |
| 125 | 126 | ||
| @@ -191,6 +192,14 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 191 | return 6; | 192 | return 6; |
| 192 | } | 193 | } |
| 193 | return 0; | 194 | return 0; |
| 195 | case TextureFormat::BF10GF11RF11: | ||
| 196 | if (component == 1 || component == 2) { | ||
| 197 | return 11; | ||
| 198 | } | ||
| 199 | if (component == 0) { | ||
| 200 | return 10; | ||
| 201 | } | ||
| 202 | return 0; | ||
| 194 | case TextureFormat::G8R24: | 203 | case TextureFormat::G8R24: |
| 195 | if (component == 0) { | 204 | if (component == 0) { |
| 196 | return 8; | 205 | return 8; |
| @@ -211,10 +220,9 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 211 | return (component == 0 || component == 1) ? 8 : 0; | 220 | return (component == 0 || component == 1) ? 8 : 0; |
| 212 | case TextureFormat::G4R4: | 221 | case TextureFormat::G4R4: |
| 213 | return (component == 0 || component == 1) ? 4 : 0; | 222 | return (component == 0 || component == 1) ? 4 : 0; |
| 214 | default: | ||
| 215 | UNIMPLEMENTED_MSG("texture format not implement={}", format); | ||
| 216 | return 0; | ||
| 217 | } | 223 | } |
| 224 | UNIMPLEMENTED_MSG("Texture format not implemented={}", format); | ||
| 225 | return 0; | ||
| 218 | } | 226 | } |
| 219 | 227 | ||
| 220 | std::size_t GetImageComponentMask(TextureFormat format) { | 228 | std::size_t GetImageComponentMask(TextureFormat format) { |
| @@ -235,6 +243,7 @@ std::size_t GetImageComponentMask(TextureFormat format) { | |||
| 235 | case TextureFormat::R32_B24G8: | 243 | case TextureFormat::R32_B24G8: |
| 236 | case TextureFormat::B5G6R5: | 244 | case TextureFormat::B5G6R5: |
| 237 | case TextureFormat::B6G5R5: | 245 | case TextureFormat::B6G5R5: |
| 246 | case TextureFormat::BF10GF11RF11: | ||
| 238 | return std::size_t{R | G | B}; | 247 | return std::size_t{R | G | B}; |
| 239 | case TextureFormat::R32_G32: | 248 | case TextureFormat::R32_G32: |
| 240 | case TextureFormat::R16_G16: | 249 | case TextureFormat::R16_G16: |
| @@ -248,10 +257,9 @@ std::size_t GetImageComponentMask(TextureFormat format) { | |||
| 248 | case TextureFormat::R8: | 257 | case TextureFormat::R8: |
| 249 | case TextureFormat::R1: | 258 | case TextureFormat::R1: |
| 250 | return std::size_t{R}; | 259 | return std::size_t{R}; |
| 251 | default: | ||
| 252 | UNIMPLEMENTED_MSG("texture format not implement={}", format); | ||
| 253 | return std::size_t{R | G | B | A}; | ||
| 254 | } | 260 | } |
| 261 | UNIMPLEMENTED_MSG("Texture format not implemented={}", format); | ||
| 262 | return std::size_t{R | G | B | A}; | ||
| 255 | } | 263 | } |
| 256 | 264 | ||
| 257 | std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) { | 265 | std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) { |
| @@ -299,7 +307,7 @@ std::pair<Node, bool> ShaderIR::GetComponentValue(ComponentType component_type, | |||
| 299 | return {std::move(original_value), true}; | 307 | return {std::move(original_value), true}; |
| 300 | } | 308 | } |
| 301 | default: | 309 | default: |
| 302 | UNIMPLEMENTED_MSG("Unimplement component type={}", component_type); | 310 | UNIMPLEMENTED_MSG("Unimplemented component type={}", component_type); |
| 303 | return {std::move(original_value), true}; | 311 | return {std::move(original_value), true}; |
| 304 | } | 312 | } |
| 305 | } | 313 | } |
| @@ -459,7 +467,7 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 459 | default: | 467 | default: |
| 460 | break; | 468 | break; |
| 461 | } | 469 | } |
| 462 | UNIMPLEMENTED_MSG("Unimplemented operation={} type={}", | 470 | UNIMPLEMENTED_MSG("Unimplemented operation={}, type={}", |
| 463 | static_cast<u64>(instr.suatom_d.operation.Value()), | 471 | static_cast<u64>(instr.suatom_d.operation.Value()), |
| 464 | static_cast<u64>(instr.suatom_d.operation_type.Value())); | 472 | static_cast<u64>(instr.suatom_d.operation_type.Value())); |
| 465 | return OperationCode::AtomicImageAdd; | 473 | return OperationCode::AtomicImageAdd; |
diff --git a/src/video_core/shader/memory_util.cpp b/src/video_core/shader/memory_util.cpp index 074f21691..5071c83ca 100644 --- a/src/video_core/shader/memory_util.cpp +++ b/src/video_core/shader/memory_util.cpp | |||
| @@ -66,12 +66,12 @@ ProgramCode GetShaderCode(Tegra::MemoryManager& memory_manager, GPUVAddr gpu_add | |||
| 66 | 66 | ||
| 67 | u64 GetUniqueIdentifier(Tegra::Engines::ShaderType shader_type, bool is_a, const ProgramCode& code, | 67 | u64 GetUniqueIdentifier(Tegra::Engines::ShaderType shader_type, bool is_a, const ProgramCode& code, |
| 68 | const ProgramCode& code_b) { | 68 | const ProgramCode& code_b) { |
| 69 | u64 unique_identifier = boost::hash_value(code); | 69 | size_t unique_identifier = boost::hash_value(code); |
| 70 | if (is_a) { | 70 | if (is_a) { |
| 71 | // VertexA programs include two programs | 71 | // VertexA programs include two programs |
| 72 | boost::hash_combine(unique_identifier, boost::hash_value(code_b)); | 72 | boost::hash_combine(unique_identifier, boost::hash_value(code_b)); |
| 73 | } | 73 | } |
| 74 | return unique_identifier; | 74 | return static_cast<u64>(unique_identifier); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | } // namespace VideoCommon::Shader | 77 | } // namespace VideoCommon::Shader |
diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h index a23c23886..2dd270e99 100644 --- a/src/video_core/shader_cache.h +++ b/src/video_core/shader_cache.h | |||
| @@ -19,7 +19,7 @@ namespace VideoCommon { | |||
| 19 | 19 | ||
| 20 | template <class T> | 20 | template <class T> |
| 21 | class ShaderCache { | 21 | class ShaderCache { |
| 22 | static constexpr u64 PAGE_SHIFT = 14; | 22 | static constexpr u64 PAGE_BITS = 14; |
| 23 | 23 | ||
| 24 | struct Entry { | 24 | struct Entry { |
| 25 | VAddr addr_start; | 25 | VAddr addr_start; |
| @@ -87,8 +87,8 @@ protected: | |||
| 87 | const VAddr addr_end = addr + size; | 87 | const VAddr addr_end = addr + size; |
| 88 | Entry* const entry = NewEntry(addr, addr_end, data.get()); | 88 | Entry* const entry = NewEntry(addr, addr_end, data.get()); |
| 89 | 89 | ||
| 90 | const u64 page_end = addr_end >> PAGE_SHIFT; | 90 | const u64 page_end = addr_end >> PAGE_BITS; |
| 91 | for (u64 page = addr >> PAGE_SHIFT; page <= page_end; ++page) { | 91 | for (u64 page = addr >> PAGE_BITS; page <= page_end; ++page) { |
| 92 | invalidation_cache[page].push_back(entry); | 92 | invalidation_cache[page].push_back(entry); |
| 93 | } | 93 | } |
| 94 | 94 | ||
| @@ -108,8 +108,8 @@ private: | |||
| 108 | /// @pre invalidation_mutex is locked | 108 | /// @pre invalidation_mutex is locked |
| 109 | void InvalidatePagesInRegion(VAddr addr, std::size_t size) { | 109 | void InvalidatePagesInRegion(VAddr addr, std::size_t size) { |
| 110 | const VAddr addr_end = addr + size; | 110 | const VAddr addr_end = addr + size; |
| 111 | const u64 page_end = addr_end >> PAGE_SHIFT; | 111 | const u64 page_end = addr_end >> PAGE_BITS; |
| 112 | for (u64 page = addr >> PAGE_SHIFT; page <= page_end; ++page) { | 112 | for (u64 page = addr >> PAGE_BITS; page <= page_end; ++page) { |
| 113 | const auto it = invalidation_cache.find(page); | 113 | const auto it = invalidation_cache.find(page); |
| 114 | if (it == invalidation_cache.end()) { | 114 | if (it == invalidation_cache.end()) { |
| 115 | continue; | 115 | continue; |
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index 94d3a6ae5..0caf3b4f0 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -120,6 +120,9 @@ std::optional<std::pair<u32, u32>> SurfaceBaseImpl::GetLayerMipmap( | |||
| 120 | } | 120 | } |
| 121 | const auto relative_address{static_cast<GPUVAddr>(candidate_gpu_addr - gpu_addr)}; | 121 | const auto relative_address{static_cast<GPUVAddr>(candidate_gpu_addr - gpu_addr)}; |
| 122 | const auto layer{static_cast<u32>(relative_address / layer_size)}; | 122 | const auto layer{static_cast<u32>(relative_address / layer_size)}; |
| 123 | if (layer >= params.depth) { | ||
| 124 | return {}; | ||
| 125 | } | ||
| 123 | const GPUVAddr mipmap_address = relative_address - layer_size * layer; | 126 | const GPUVAddr mipmap_address = relative_address - layer_size * layer; |
| 124 | const auto mipmap_it = | 127 | const auto mipmap_it = |
| 125 | Common::BinaryFind(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); | 128 | Common::BinaryFind(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index b543fc8c0..85075e868 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -1053,7 +1053,7 @@ private: | |||
| 1053 | void DeduceBestBlit(SurfaceParams& src_params, SurfaceParams& dst_params, | 1053 | void DeduceBestBlit(SurfaceParams& src_params, SurfaceParams& dst_params, |
| 1054 | const GPUVAddr src_gpu_addr, const GPUVAddr dst_gpu_addr) { | 1054 | const GPUVAddr src_gpu_addr, const GPUVAddr dst_gpu_addr) { |
| 1055 | auto deduced_src = DeduceSurface(src_gpu_addr, src_params); | 1055 | auto deduced_src = DeduceSurface(src_gpu_addr, src_params); |
| 1056 | auto deduced_dst = DeduceSurface(src_gpu_addr, src_params); | 1056 | auto deduced_dst = DeduceSurface(dst_gpu_addr, dst_params); |
| 1057 | if (deduced_src.Failed() || deduced_dst.Failed()) { | 1057 | if (deduced_src.Failed() || deduced_dst.Failed()) { |
| 1058 | return; | 1058 | return; |
| 1059 | } | 1059 | } |
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 8b9404718..75c27e39e 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -208,6 +208,10 @@ if (MSVC) | |||
| 208 | copy_yuzu_unicorn_deps(yuzu) | 208 | copy_yuzu_unicorn_deps(yuzu) |
| 209 | endif() | 209 | endif() |
| 210 | 210 | ||
| 211 | if (NOT APPLE) | ||
| 212 | target_compile_definitions(yuzu PRIVATE HAS_OPENGL) | ||
| 213 | endif() | ||
| 214 | |||
| 211 | if (ENABLE_VULKAN) | 215 | if (ENABLE_VULKAN) |
| 212 | target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) | 216 | target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include) |
| 213 | target_compile_definitions(yuzu PRIVATE HAS_VULKAN) | 217 | target_compile_definitions(yuzu PRIVATE HAS_VULKAN) |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 1f5e43043..bfeb16458 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -8,13 +8,16 @@ | |||
| 8 | #include <QHBoxLayout> | 8 | #include <QHBoxLayout> |
| 9 | #include <QKeyEvent> | 9 | #include <QKeyEvent> |
| 10 | #include <QMessageBox> | 10 | #include <QMessageBox> |
| 11 | #include <QOffscreenSurface> | ||
| 12 | #include <QOpenGLContext> | ||
| 13 | #include <QPainter> | 11 | #include <QPainter> |
| 14 | #include <QScreen> | 12 | #include <QScreen> |
| 15 | #include <QStringList> | 13 | #include <QStringList> |
| 16 | #include <QWindow> | 14 | #include <QWindow> |
| 17 | 15 | ||
| 16 | #ifdef HAS_OPENGL | ||
| 17 | #include <QOffscreenSurface> | ||
| 18 | #include <QOpenGLContext> | ||
| 19 | #endif | ||
| 20 | |||
| 18 | #if !defined(WIN32) && HAS_VULKAN | 21 | #if !defined(WIN32) && HAS_VULKAN |
| 19 | #include <qpa/qplatformnativeinterface.h> | 22 | #include <qpa/qplatformnativeinterface.h> |
| 20 | #endif | 23 | #endif |
| @@ -98,6 +101,7 @@ void EmuThread::run() { | |||
| 98 | #endif | 101 | #endif |
| 99 | } | 102 | } |
| 100 | 103 | ||
| 104 | #ifdef HAS_OPENGL | ||
| 101 | class OpenGLSharedContext : public Core::Frontend::GraphicsContext { | 105 | class OpenGLSharedContext : public Core::Frontend::GraphicsContext { |
| 102 | public: | 106 | public: |
| 103 | /// Create the original context that should be shared from | 107 | /// Create the original context that should be shared from |
| @@ -183,6 +187,7 @@ private: | |||
| 183 | std::unique_ptr<QOffscreenSurface> offscreen_surface{}; | 187 | std::unique_ptr<QOffscreenSurface> offscreen_surface{}; |
| 184 | QSurface* surface; | 188 | QSurface* surface; |
| 185 | }; | 189 | }; |
| 190 | #endif | ||
| 186 | 191 | ||
| 187 | class DummyContext : public Core::Frontend::GraphicsContext {}; | 192 | class DummyContext : public Core::Frontend::GraphicsContext {}; |
| 188 | 193 | ||
| @@ -355,7 +360,7 @@ QByteArray GRenderWindow::saveGeometry() { | |||
| 355 | } | 360 | } |
| 356 | 361 | ||
| 357 | qreal GRenderWindow::windowPixelRatio() const { | 362 | qreal GRenderWindow::windowPixelRatio() const { |
| 358 | return devicePixelRatio(); | 363 | return devicePixelRatioF(); |
| 359 | } | 364 | } |
| 360 | 365 | ||
| 361 | std::pair<u32, u32> GRenderWindow::ScaleTouch(const QPointF& pos) const { | 366 | std::pair<u32, u32> GRenderWindow::ScaleTouch(const QPointF& pos) const { |
| @@ -473,6 +478,7 @@ void GRenderWindow::resizeEvent(QResizeEvent* event) { | |||
| 473 | } | 478 | } |
| 474 | 479 | ||
| 475 | std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { | 480 | std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { |
| 481 | #ifdef HAS_OPENGL | ||
| 476 | if (Settings::values.renderer_backend == Settings::RendererBackend::OpenGL) { | 482 | if (Settings::values.renderer_backend == Settings::RendererBackend::OpenGL) { |
| 477 | auto c = static_cast<OpenGLSharedContext*>(main_context.get()); | 483 | auto c = static_cast<OpenGLSharedContext*>(main_context.get()); |
| 478 | // Bind the shared contexts to the main surface in case the backend wants to take over | 484 | // Bind the shared contexts to the main surface in case the backend wants to take over |
| @@ -480,6 +486,7 @@ std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedCont | |||
| 480 | return std::make_unique<OpenGLSharedContext>(c->GetShareContext(), | 486 | return std::make_unique<OpenGLSharedContext>(c->GetShareContext(), |
| 481 | child_widget->windowHandle()); | 487 | child_widget->windowHandle()); |
| 482 | } | 488 | } |
| 489 | #endif | ||
| 483 | return std::make_unique<DummyContext>(); | 490 | return std::make_unique<DummyContext>(); |
| 484 | } | 491 | } |
| 485 | 492 | ||
| @@ -560,6 +567,7 @@ void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal | |||
| 560 | } | 567 | } |
| 561 | 568 | ||
| 562 | bool GRenderWindow::InitializeOpenGL() { | 569 | bool GRenderWindow::InitializeOpenGL() { |
| 570 | #ifdef HAS_OPENGL | ||
| 563 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, | 571 | // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, |
| 564 | // WA_DontShowOnScreen, WA_DeleteOnClose | 572 | // WA_DontShowOnScreen, WA_DeleteOnClose |
| 565 | auto child = new OpenGLRenderWidget(this); | 573 | auto child = new OpenGLRenderWidget(this); |
| @@ -571,6 +579,11 @@ bool GRenderWindow::InitializeOpenGL() { | |||
| 571 | std::make_unique<OpenGLSharedContext>(context->GetShareContext(), child->windowHandle())); | 579 | std::make_unique<OpenGLSharedContext>(context->GetShareContext(), child->windowHandle())); |
| 572 | 580 | ||
| 573 | return true; | 581 | return true; |
| 582 | #else | ||
| 583 | QMessageBox::warning(this, tr("OpenGL not available!"), | ||
| 584 | tr("yuzu has not been compiled with OpenGL support.")); | ||
| 585 | return false; | ||
| 586 | #endif | ||
| 574 | } | 587 | } |
| 575 | 588 | ||
| 576 | bool GRenderWindow::InitializeVulkan() { | 589 | bool GRenderWindow::InitializeVulkan() { |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 32c81dc70..bbbd96113 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -211,7 +211,7 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default | |||
| 211 | // This must be in alphabetical order according to action name as it must have the same order as | 211 | // This must be in alphabetical order according to action name as it must have the same order as |
| 212 | // UISetting::values.shortcuts, which is alphabetically ordered. | 212 | // UISetting::values.shortcuts, which is alphabetically ordered. |
| 213 | // clang-format off | 213 | // clang-format off |
| 214 | const std::array<UISettings::Shortcut, 15> Config::default_hotkeys{{ | 214 | const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{ |
| 215 | {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::ApplicationShortcut}}, | 215 | {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::ApplicationShortcut}}, |
| 216 | {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}}, | 216 | {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}}, |
| 217 | {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, | 217 | {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, |
| @@ -222,6 +222,7 @@ const std::array<UISettings::Shortcut, 15> Config::default_hotkeys{{ | |||
| 222 | {QStringLiteral("Increase Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("+"), Qt::ApplicationShortcut}}, | 222 | {QStringLiteral("Increase Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("+"), Qt::ApplicationShortcut}}, |
| 223 | {QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::ApplicationShortcut}}, | 223 | {QStringLiteral("Load Amiibo"), QStringLiteral("Main Window"), {QStringLiteral("F2"), Qt::ApplicationShortcut}}, |
| 224 | {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WindowShortcut}}, | 224 | {QStringLiteral("Load File"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+O"), Qt::WindowShortcut}}, |
| 225 | {QStringLiteral("Mute Audio"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+M"), Qt::WindowShortcut}}, | ||
| 225 | {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, | 226 | {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, |
| 226 | {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, | 227 | {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, |
| 227 | {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, | 228 | {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 5cd2a5feb..09316382c 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -27,7 +27,7 @@ public: | |||
| 27 | default_mouse_buttons; | 27 | default_mouse_buttons; |
| 28 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; | 28 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; |
| 29 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; | 29 | static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; |
| 30 | static const std::array<UISettings::Shortcut, 15> default_hotkeys; | 30 | static const std::array<UISettings::Shortcut, 16> default_hotkeys; |
| 31 | 31 | ||
| 32 | private: | 32 | private: |
| 33 | void ReadValues(); | 33 | void ReadValues(); |
diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_service.cpp index 06566e981..0de7a4f0b 100644 --- a/src/yuzu/configuration/configure_service.cpp +++ b/src/yuzu/configuration/configure_service.cpp | |||
| @@ -68,6 +68,7 @@ void ConfigureService::SetConfiguration() { | |||
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { | 70 | std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { |
| 71 | #ifdef YUZU_ENABLE_BOXCAT | ||
| 71 | std::optional<std::string> global; | 72 | std::optional<std::string> global; |
| 72 | std::map<std::string, Service::BCAT::EventStatus> map; | 73 | std::map<std::string, Service::BCAT::EventStatus> map; |
| 73 | const auto res = Service::BCAT::Boxcat::GetStatus(global, map); | 74 | const auto res = Service::BCAT::Boxcat::GetStatus(global, map); |
| @@ -105,7 +106,10 @@ std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { | |||
| 105 | .arg(QString::fromStdString(key)) | 106 | .arg(QString::fromStdString(key)) |
| 106 | .arg(FormatEventStatusString(value)); | 107 | .arg(FormatEventStatusString(value)); |
| 107 | } | 108 | } |
| 108 | return {QStringLiteral("Current Boxcat Events"), std::move(out)}; | 109 | return {tr("Current Boxcat Events"), std::move(out)}; |
| 110 | #else | ||
| 111 | return {tr("Current Boxcat Events"), tr("There are currently no events on boxcat.")}; | ||
| 112 | #endif | ||
| 109 | } | 113 | } |
| 110 | 114 | ||
| 111 | void ConfigureService::OnBCATImplChanged() { | 115 | void ConfigureService::OnBCATImplChanged() { |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 4119d7907..ba69139e5 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -56,6 +56,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 56 | #include <QShortcut> | 56 | #include <QShortcut> |
| 57 | #include <QStatusBar> | 57 | #include <QStatusBar> |
| 58 | #include <QSysInfo> | 58 | #include <QSysInfo> |
| 59 | #include <QUrl> | ||
| 59 | #include <QtConcurrent/QtConcurrent> | 60 | #include <QtConcurrent/QtConcurrent> |
| 60 | 61 | ||
| 61 | #include <fmt/format.h> | 62 | #include <fmt/format.h> |
| @@ -217,7 +218,20 @@ GMainWindow::GMainWindow() | |||
| 217 | LOG_INFO(Frontend, "yuzu Version: {} | {}-{}", yuzu_build_version, Common::g_scm_branch, | 218 | LOG_INFO(Frontend, "yuzu Version: {} | {}-{}", yuzu_build_version, Common::g_scm_branch, |
| 218 | Common::g_scm_desc); | 219 | Common::g_scm_desc); |
| 219 | #ifdef ARCHITECTURE_x86_64 | 220 | #ifdef ARCHITECTURE_x86_64 |
| 220 | LOG_INFO(Frontend, "Host CPU: {}", Common::GetCPUCaps().cpu_string); | 221 | const auto& caps = Common::GetCPUCaps(); |
| 222 | std::string cpu_string = caps.cpu_string; | ||
| 223 | if (caps.avx || caps.avx2 || caps.avx512) { | ||
| 224 | cpu_string += " | AVX"; | ||
| 225 | if (caps.avx512) { | ||
| 226 | cpu_string += "512"; | ||
| 227 | } else if (caps.avx2) { | ||
| 228 | cpu_string += '2'; | ||
| 229 | } | ||
| 230 | if (caps.fma || caps.fma4) { | ||
| 231 | cpu_string += " | FMA"; | ||
| 232 | } | ||
| 233 | } | ||
| 234 | LOG_INFO(Frontend, "Host CPU: {}", cpu_string); | ||
| 221 | #endif | 235 | #endif |
| 222 | LOG_INFO(Frontend, "Host OS: {}", QSysInfo::prettyProductName().toStdString()); | 236 | LOG_INFO(Frontend, "Host OS: {}", QSysInfo::prettyProductName().toStdString()); |
| 223 | LOG_INFO(Frontend, "Host RAM: {:.2f} GB", | 237 | LOG_INFO(Frontend, "Host RAM: {:.2f} GB", |
| @@ -723,6 +737,9 @@ void GMainWindow::InitializeHotkeys() { | |||
| 723 | Settings::values.use_docked_mode); | 737 | Settings::values.use_docked_mode); |
| 724 | dock_status_button->setChecked(Settings::values.use_docked_mode); | 738 | dock_status_button->setChecked(Settings::values.use_docked_mode); |
| 725 | }); | 739 | }); |
| 740 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), | ||
| 741 | &QShortcut::activated, this, | ||
| 742 | [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); | ||
| 726 | } | 743 | } |
| 727 | 744 | ||
| 728 | void GMainWindow::SetDefaultUIGeometry() { | 745 | void GMainWindow::SetDefaultUIGeometry() { |
| @@ -823,6 +840,7 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 823 | connect(ui.action_Stop, &QAction::triggered, this, &GMainWindow::OnStopGame); | 840 | connect(ui.action_Stop, &QAction::triggered, this, &GMainWindow::OnStopGame); |
| 824 | connect(ui.action_Report_Compatibility, &QAction::triggered, this, | 841 | connect(ui.action_Report_Compatibility, &QAction::triggered, this, |
| 825 | &GMainWindow::OnMenuReportCompatibility); | 842 | &GMainWindow::OnMenuReportCompatibility); |
| 843 | connect(ui.action_Open_Mods_Page, &QAction::triggered, this, &GMainWindow::OnOpenModsPage); | ||
| 826 | connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); | 844 | connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); |
| 827 | connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); | 845 | connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); |
| 828 | 846 | ||
| @@ -1794,6 +1812,16 @@ void GMainWindow::OnMenuReportCompatibility() { | |||
| 1794 | } | 1812 | } |
| 1795 | } | 1813 | } |
| 1796 | 1814 | ||
| 1815 | void GMainWindow::OnOpenModsPage() { | ||
| 1816 | const auto mods_page_url = QStringLiteral("https://github.com/yuzu-emu/yuzu/wiki/Switch-Mods"); | ||
| 1817 | const QUrl mods_page(mods_page_url); | ||
| 1818 | const bool open = QDesktopServices::openUrl(mods_page); | ||
| 1819 | if (!open) { | ||
| 1820 | QMessageBox::warning(this, tr("Error opening URL"), | ||
| 1821 | tr("Unable to open the URL \"%1\".").arg(mods_page_url)); | ||
| 1822 | } | ||
| 1823 | } | ||
| 1824 | |||
| 1797 | void GMainWindow::ToggleFullscreen() { | 1825 | void GMainWindow::ToggleFullscreen() { |
| 1798 | if (!emulation_running) { | 1826 | if (!emulation_running) { |
| 1799 | return; | 1827 | return; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 4f4c8ddbe..d55e55cc6 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -181,6 +181,7 @@ private slots: | |||
| 181 | void OnPauseGame(); | 181 | void OnPauseGame(); |
| 182 | void OnStopGame(); | 182 | void OnStopGame(); |
| 183 | void OnMenuReportCompatibility(); | 183 | void OnMenuReportCompatibility(); |
| 184 | void OnOpenModsPage(); | ||
| 184 | /// Called whenever a user selects a game in the game list widget. | 185 | /// Called whenever a user selects a game in the game list widget. |
| 185 | void OnGameListLoadFile(QString game_path); | 186 | void OnGameListLoadFile(QString game_path); |
| 186 | void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path); | 187 | void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path); |
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 97c90f50b..b5745dfd5 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui | |||
| @@ -113,6 +113,7 @@ | |||
| 113 | <string>&Help</string> | 113 | <string>&Help</string> |
| 114 | </property> | 114 | </property> |
| 115 | <addaction name="action_Report_Compatibility"/> | 115 | <addaction name="action_Report_Compatibility"/> |
| 116 | <addaction name="action_Open_Mods_Page"/> | ||
| 116 | <addaction name="separator"/> | 117 | <addaction name="separator"/> |
| 117 | <addaction name="action_About"/> | 118 | <addaction name="action_About"/> |
| 118 | </widget> | 119 | </widget> |
| @@ -256,6 +257,11 @@ | |||
| 256 | <bool>false</bool> | 257 | <bool>false</bool> |
| 257 | </property> | 258 | </property> |
| 258 | </action> | 259 | </action> |
| 260 | <action name="action_Open_Mods_Page"> | ||
| 261 | <property name="text"> | ||
| 262 | <string>Open Mods Page</string> | ||
| 263 | </property> | ||
| 264 | </action> | ||
| 259 | <action name="action_Open_yuzu_Folder"> | 265 | <action name="action_Open_yuzu_Folder"> |
| 260 | <property name="text"> | 266 | <property name="text"> |
| 261 | <string>Open yuzu Folder</string> | 267 | <string>Open yuzu Folder</string> |
diff --git a/src/yuzu/yuzu.rc b/src/yuzu/yuzu.rc index 1b253653f..4a3645a71 100644 --- a/src/yuzu/yuzu.rc +++ b/src/yuzu/yuzu.rc | |||
| @@ -16,4 +16,4 @@ IDI_ICON1 ICON "../../dist/yuzu.ico" | |||
| 16 | // RT_MANIFEST | 16 | // RT_MANIFEST |
| 17 | // | 17 | // |
| 18 | 18 | ||
| 19 | 1 RT_MANIFEST "../../dist/yuzu.manifest" | 19 | 0 RT_MANIFEST "../../dist/yuzu.manifest" |
diff --git a/src/yuzu_cmd/yuzu.rc b/src/yuzu_cmd/yuzu.rc index 7de8ef3d9..0cde75e2f 100644 --- a/src/yuzu_cmd/yuzu.rc +++ b/src/yuzu_cmd/yuzu.rc | |||
| @@ -14,4 +14,4 @@ YUZU_ICON ICON "../../dist/yuzu.ico" | |||
| 14 | // RT_MANIFEST | 14 | // RT_MANIFEST |
| 15 | // | 15 | // |
| 16 | 16 | ||
| 17 | 1 RT_MANIFEST "../../dist/yuzu.manifest" | 17 | 0 RT_MANIFEST "../../dist/yuzu.manifest" |
diff --git a/src/yuzu_tester/service/yuzutest.cpp b/src/yuzu_tester/service/yuzutest.cpp index 85d3f436b..2d3f6e3a7 100644 --- a/src/yuzu_tester/service/yuzutest.cpp +++ b/src/yuzu_tester/service/yuzutest.cpp | |||
| @@ -53,7 +53,7 @@ private: | |||
| 53 | 53 | ||
| 54 | IPC::ResponseBuilder rb{ctx, 3}; | 54 | IPC::ResponseBuilder rb{ctx, 3}; |
| 55 | rb.Push(RESULT_SUCCESS); | 55 | rb.Push(RESULT_SUCCESS); |
| 56 | rb.Push<u32>(write_size); | 56 | rb.Push<u32>(static_cast<u32>(write_size)); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | void StartIndividual(Kernel::HLERequestContext& ctx) { | 59 | void StartIndividual(Kernel::HLERequestContext& ctx) { |
diff --git a/src/yuzu_tester/yuzu.rc b/src/yuzu_tester/yuzu.rc index 7de8ef3d9..0cde75e2f 100644 --- a/src/yuzu_tester/yuzu.rc +++ b/src/yuzu_tester/yuzu.rc | |||
| @@ -14,4 +14,4 @@ YUZU_ICON ICON "../../dist/yuzu.ico" | |||
| 14 | // RT_MANIFEST | 14 | // RT_MANIFEST |
| 15 | // | 15 | // |
| 16 | 16 | ||
| 17 | 1 RT_MANIFEST "../../dist/yuzu.manifest" | 17 | 0 RT_MANIFEST "../../dist/yuzu.manifest" |