diff options
Diffstat (limited to 'src')
80 files changed, 1153 insertions, 1147 deletions
diff --git a/src/audio_core/audio_renderer.cpp b/src/audio_core/audio_renderer.cpp index 23e5d3f10..2e59894ab 100644 --- a/src/audio_core/audio_renderer.cpp +++ b/src/audio_core/audio_renderer.cpp | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | #include "audio_core/codec.h" | 8 | #include "audio_core/codec.h" |
| 9 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "core/hle/kernel/event.h" | 11 | #include "core/hle/kernel/writable_event.h" |
| 12 | #include "core/memory.h" | 12 | #include "core/memory.h" |
| 13 | 13 | ||
| 14 | namespace AudioCore { | 14 | namespace AudioCore { |
| @@ -72,7 +72,7 @@ private: | |||
| 72 | EffectInStatus info{}; | 72 | EffectInStatus info{}; |
| 73 | }; | 73 | }; |
| 74 | AudioRenderer::AudioRenderer(AudioRendererParameter params, | 74 | AudioRenderer::AudioRenderer(AudioRendererParameter params, |
| 75 | Kernel::SharedPtr<Kernel::Event> buffer_event) | 75 | Kernel::SharedPtr<Kernel::WritableEvent> buffer_event) |
| 76 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count), | 76 | : worker_params{params}, buffer_event{buffer_event}, voices(params.voice_count), |
| 77 | effects(params.effect_count) { | 77 | effects(params.effect_count) { |
| 78 | 78 | ||
diff --git a/src/audio_core/audio_renderer.h b/src/audio_core/audio_renderer.h index 71ba4be40..7826881bf 100644 --- a/src/audio_core/audio_renderer.h +++ b/src/audio_core/audio_renderer.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #include "core/hle/kernel/object.h" | 15 | #include "core/hle/kernel/object.h" |
| 16 | 16 | ||
| 17 | namespace Kernel { | 17 | namespace Kernel { |
| 18 | class Event; | 18 | class WritableEvent; |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | namespace AudioCore { | 21 | namespace AudioCore { |
| @@ -208,7 +208,8 @@ static_assert(sizeof(UpdateDataHeader) == 0x40, "UpdateDataHeader has wrong size | |||
| 208 | 208 | ||
| 209 | class AudioRenderer { | 209 | class AudioRenderer { |
| 210 | public: | 210 | public: |
| 211 | AudioRenderer(AudioRendererParameter params, Kernel::SharedPtr<Kernel::Event> buffer_event); | 211 | AudioRenderer(AudioRendererParameter params, |
| 212 | Kernel::SharedPtr<Kernel::WritableEvent> buffer_event); | ||
| 212 | ~AudioRenderer(); | 213 | ~AudioRenderer(); |
| 213 | 214 | ||
| 214 | std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params); | 215 | std::vector<u8> UpdateAudioRenderer(const std::vector<u8>& input_params); |
| @@ -224,7 +225,7 @@ private: | |||
| 224 | class VoiceState; | 225 | class VoiceState; |
| 225 | 226 | ||
| 226 | AudioRendererParameter worker_params; | 227 | AudioRendererParameter worker_params; |
| 227 | Kernel::SharedPtr<Kernel::Event> buffer_event; | 228 | Kernel::SharedPtr<Kernel::WritableEvent> buffer_event; |
| 228 | std::vector<VoiceState> voices; | 229 | std::vector<VoiceState> voices; |
| 229 | std::vector<EffectState> effects; | 230 | std::vector<EffectState> effects; |
| 230 | std::unique_ptr<AudioOut> audio_out; | 231 | std::unique_ptr<AudioOut> audio_out; |
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e1f21a764..73aec8ab0 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -97,8 +97,6 @@ add_library(core STATIC | |||
| 97 | hle/kernel/client_session.cpp | 97 | hle/kernel/client_session.cpp |
| 98 | hle/kernel/client_session.h | 98 | hle/kernel/client_session.h |
| 99 | hle/kernel/errors.h | 99 | hle/kernel/errors.h |
| 100 | hle/kernel/event.cpp | ||
| 101 | hle/kernel/event.h | ||
| 102 | hle/kernel/handle_table.cpp | 100 | hle/kernel/handle_table.cpp |
| 103 | hle/kernel/handle_table.h | 101 | hle/kernel/handle_table.h |
| 104 | hle/kernel/hle_ipc.cpp | 102 | hle/kernel/hle_ipc.cpp |
| @@ -111,6 +109,8 @@ add_library(core STATIC | |||
| 111 | hle/kernel/object.h | 109 | hle/kernel/object.h |
| 112 | hle/kernel/process.cpp | 110 | hle/kernel/process.cpp |
| 113 | hle/kernel/process.h | 111 | hle/kernel/process.h |
| 112 | hle/kernel/readable_event.cpp | ||
| 113 | hle/kernel/readable_event.h | ||
| 114 | hle/kernel/resource_limit.cpp | 114 | hle/kernel/resource_limit.cpp |
| 115 | hle/kernel/resource_limit.h | 115 | hle/kernel/resource_limit.h |
| 116 | hle/kernel/scheduler.cpp | 116 | hle/kernel/scheduler.cpp |
| @@ -133,6 +133,8 @@ add_library(core STATIC | |||
| 133 | hle/kernel/vm_manager.h | 133 | hle/kernel/vm_manager.h |
| 134 | hle/kernel/wait_object.cpp | 134 | hle/kernel/wait_object.cpp |
| 135 | hle/kernel/wait_object.h | 135 | hle/kernel/wait_object.h |
| 136 | hle/kernel/writable_event.cpp | ||
| 137 | hle/kernel/writable_event.h | ||
| 136 | hle/lock.cpp | 138 | hle/lock.cpp |
| 137 | hle/lock.h | 139 | hle/lock.h |
| 138 | hle/result.h | 140 | hle/result.h |
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 291624cbe..ca12fb4ab 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp | |||
| @@ -793,7 +793,7 @@ void KeyManager::DeriveBase() { | |||
| 793 | 793 | ||
| 794 | void KeyManager::DeriveETicket(PartitionDataManager& data) { | 794 | void KeyManager::DeriveETicket(PartitionDataManager& data) { |
| 795 | // ETicket keys | 795 | // ETicket keys |
| 796 | const auto es = Service::FileSystem::GetUnionContents()->GetEntry( | 796 | const auto es = Service::FileSystem::GetUnionContents().GetEntry( |
| 797 | 0x0100000000000033, FileSys::ContentRecordType::Program); | 797 | 0x0100000000000033, FileSys::ContentRecordType::Program); |
| 798 | 798 | ||
| 799 | if (es == nullptr) | 799 | if (es == nullptr) |
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index e8df08724..6b14e08be 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -75,12 +75,12 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 75 | 75 | ||
| 76 | // Game Updates | 76 | // Game Updates |
| 77 | const auto update_tid = GetUpdateTitleID(title_id); | 77 | const auto update_tid = GetUpdateTitleID(title_id); |
| 78 | const auto update = installed->GetEntry(update_tid, ContentRecordType::Program); | 78 | const auto update = installed.GetEntry(update_tid, ContentRecordType::Program); |
| 79 | 79 | ||
| 80 | if (update != nullptr && update->GetExeFS() != nullptr && | 80 | if (update != nullptr && update->GetExeFS() != nullptr && |
| 81 | update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { | 81 | update->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) { |
| 82 | LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully", | 82 | LOG_INFO(Loader, " ExeFS: Update ({}) applied successfully", |
| 83 | FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0))); | 83 | FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); |
| 84 | exefs = update->GetExeFS(); | 84 | exefs = update->GetExeFS(); |
| 85 | } | 85 | } |
| 86 | 86 | ||
| @@ -281,13 +281,13 @@ VirtualFile PatchManager::PatchRomFS(VirtualFile romfs, u64 ivfc_offset, Content | |||
| 281 | 281 | ||
| 282 | // Game Updates | 282 | // Game Updates |
| 283 | const auto update_tid = GetUpdateTitleID(title_id); | 283 | const auto update_tid = GetUpdateTitleID(title_id); |
| 284 | const auto update = installed->GetEntryRaw(update_tid, type); | 284 | const auto update = installed.GetEntryRaw(update_tid, type); |
| 285 | if (update != nullptr) { | 285 | if (update != nullptr) { |
| 286 | const auto new_nca = std::make_shared<NCA>(update, romfs, ivfc_offset); | 286 | const auto new_nca = std::make_shared<NCA>(update, romfs, ivfc_offset); |
| 287 | if (new_nca->GetStatus() == Loader::ResultStatus::Success && | 287 | if (new_nca->GetStatus() == Loader::ResultStatus::Success && |
| 288 | new_nca->GetRomFS() != nullptr) { | 288 | new_nca->GetRomFS() != nullptr) { |
| 289 | LOG_INFO(Loader, " RomFS: Update ({}) applied successfully", | 289 | LOG_INFO(Loader, " RomFS: Update ({}) applied successfully", |
| 290 | FormatTitleVersion(installed->GetEntryVersion(update_tid).value_or(0))); | 290 | FormatTitleVersion(installed.GetEntryVersion(update_tid).value_or(0))); |
| 291 | romfs = new_nca->GetRomFS(); | 291 | romfs = new_nca->GetRomFS(); |
| 292 | } | 292 | } |
| 293 | } else if (update_raw != nullptr) { | 293 | } else if (update_raw != nullptr) { |
| @@ -329,8 +329,8 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam | |||
| 329 | if (nacp != nullptr) { | 329 | if (nacp != nullptr) { |
| 330 | out.insert_or_assign("Update", nacp->GetVersionString()); | 330 | out.insert_or_assign("Update", nacp->GetVersionString()); |
| 331 | } else { | 331 | } else { |
| 332 | if (installed->HasEntry(update_tid, ContentRecordType::Program)) { | 332 | if (installed.HasEntry(update_tid, ContentRecordType::Program)) { |
| 333 | const auto meta_ver = installed->GetEntryVersion(update_tid); | 333 | const auto meta_ver = installed.GetEntryVersion(update_tid); |
| 334 | if (meta_ver.value_or(0) == 0) { | 334 | if (meta_ver.value_or(0) == 0) { |
| 335 | out.insert_or_assign("Update", ""); | 335 | out.insert_or_assign("Update", ""); |
| 336 | } else { | 336 | } else { |
| @@ -383,14 +383,13 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam | |||
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | // DLC | 385 | // DLC |
| 386 | const auto dlc_entries = installed->ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); | 386 | const auto dlc_entries = installed.ListEntriesFilter(TitleType::AOC, ContentRecordType::Data); |
| 387 | std::vector<RegisteredCacheEntry> dlc_match; | 387 | std::vector<RegisteredCacheEntry> dlc_match; |
| 388 | dlc_match.reserve(dlc_entries.size()); | 388 | dlc_match.reserve(dlc_entries.size()); |
| 389 | std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), | 389 | std::copy_if(dlc_entries.begin(), dlc_entries.end(), std::back_inserter(dlc_match), |
| 390 | [this, &installed](const RegisteredCacheEntry& entry) { | 390 | [this, &installed](const RegisteredCacheEntry& entry) { |
| 391 | return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id && | 391 | return (entry.title_id & DLC_BASE_TITLE_ID_MASK) == title_id && |
| 392 | installed->GetEntry(entry)->GetStatus() == | 392 | installed.GetEntry(entry)->GetStatus() == Loader::ResultStatus::Success; |
| 393 | Loader::ResultStatus::Success; | ||
| 394 | }); | 393 | }); |
| 395 | if (!dlc_match.empty()) { | 394 | if (!dlc_match.empty()) { |
| 396 | // Ensure sorted so DLC IDs show in order. | 395 | // Ensure sorted so DLC IDs show in order. |
| @@ -411,7 +410,7 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam | |||
| 411 | std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const { | 410 | std::pair<std::unique_ptr<NACP>, VirtualFile> PatchManager::GetControlMetadata() const { |
| 412 | const auto installed{Service::FileSystem::GetUnionContents()}; | 411 | const auto installed{Service::FileSystem::GetUnionContents()}; |
| 413 | 412 | ||
| 414 | const auto base_control_nca = installed->GetEntry(title_id, ContentRecordType::Control); | 413 | const auto base_control_nca = installed.GetEntry(title_id, ContentRecordType::Control); |
| 415 | if (base_control_nca == nullptr) | 414 | if (base_control_nca == nullptr) |
| 416 | return {}; | 415 | return {}; |
| 417 | 416 | ||
diff --git a/src/core/file_sys/romfs_factory.cpp b/src/core/file_sys/romfs_factory.cpp index 0b645b106..6ad1e4f86 100644 --- a/src/core/file_sys/romfs_factory.cpp +++ b/src/core/file_sys/romfs_factory.cpp | |||
| @@ -48,7 +48,7 @@ ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage, Conte | |||
| 48 | 48 | ||
| 49 | switch (storage) { | 49 | switch (storage) { |
| 50 | case StorageId::None: | 50 | case StorageId::None: |
| 51 | res = Service::FileSystem::GetUnionContents()->GetEntry(title_id, type); | 51 | res = Service::FileSystem::GetUnionContents().GetEntry(title_id, type); |
| 52 | break; | 52 | break; |
| 53 | case StorageId::NandSystem: | 53 | case StorageId::NandSystem: |
| 54 | res = Service::FileSystem::GetSystemNANDContents()->GetEntry(title_id, type); | 54 | res = Service::FileSystem::GetSystemNANDContents()->GetEntry(title_id, type); |
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp index 7b584de7f..e33327ef0 100644 --- a/src/core/file_sys/vfs.cpp +++ b/src/core/file_sys/vfs.cpp | |||
| @@ -384,6 +384,28 @@ bool VfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) { | |||
| 384 | return success; | 384 | return success; |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | bool VfsDirectory::CleanSubdirectoryRecursive(std::string_view name) { | ||
| 388 | auto dir = GetSubdirectory(name); | ||
| 389 | if (dir == nullptr) { | ||
| 390 | return false; | ||
| 391 | } | ||
| 392 | |||
| 393 | bool success = true; | ||
| 394 | for (const auto& file : dir->GetFiles()) { | ||
| 395 | if (!dir->DeleteFile(file->GetName())) { | ||
| 396 | success = false; | ||
| 397 | } | ||
| 398 | } | ||
| 399 | |||
| 400 | for (const auto& sdir : dir->GetSubdirectories()) { | ||
| 401 | if (!dir->DeleteSubdirectoryRecursive(sdir->GetName())) { | ||
| 402 | success = false; | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | return success; | ||
| 407 | } | ||
| 408 | |||
| 387 | bool VfsDirectory::Copy(std::string_view src, std::string_view dest) { | 409 | bool VfsDirectory::Copy(std::string_view src, std::string_view dest) { |
| 388 | const auto f1 = GetFile(src); | 410 | const auto f1 = GetFile(src); |
| 389 | auto f2 = CreateFile(dest); | 411 | auto f2 = CreateFile(dest); |
| @@ -431,10 +453,34 @@ std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFile(std::string_view name) | |||
| 431 | return nullptr; | 453 | return nullptr; |
| 432 | } | 454 | } |
| 433 | 455 | ||
| 456 | std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFileAbsolute(std::string_view path) { | ||
| 457 | return nullptr; | ||
| 458 | } | ||
| 459 | |||
| 460 | std::shared_ptr<VfsFile> ReadOnlyVfsDirectory::CreateFileRelative(std::string_view path) { | ||
| 461 | return nullptr; | ||
| 462 | } | ||
| 463 | |||
| 464 | std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateDirectoryAbsolute(std::string_view path) { | ||
| 465 | return nullptr; | ||
| 466 | } | ||
| 467 | |||
| 468 | std::shared_ptr<VfsDirectory> ReadOnlyVfsDirectory::CreateDirectoryRelative(std::string_view path) { | ||
| 469 | return nullptr; | ||
| 470 | } | ||
| 471 | |||
| 434 | bool ReadOnlyVfsDirectory::DeleteSubdirectory(std::string_view name) { | 472 | bool ReadOnlyVfsDirectory::DeleteSubdirectory(std::string_view name) { |
| 435 | return false; | 473 | return false; |
| 436 | } | 474 | } |
| 437 | 475 | ||
| 476 | bool ReadOnlyVfsDirectory::DeleteSubdirectoryRecursive(std::string_view name) { | ||
| 477 | return false; | ||
| 478 | } | ||
| 479 | |||
| 480 | bool ReadOnlyVfsDirectory::CleanSubdirectoryRecursive(std::string_view name) { | ||
| 481 | return false; | ||
| 482 | } | ||
| 483 | |||
| 438 | bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) { | 484 | bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) { |
| 439 | return false; | 485 | return false; |
| 440 | } | 486 | } |
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h index 002f99d4e..e5641b255 100644 --- a/src/core/file_sys/vfs.h +++ b/src/core/file_sys/vfs.h | |||
| @@ -245,12 +245,18 @@ public: | |||
| 245 | // any failure. | 245 | // any failure. |
| 246 | virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path); | 246 | virtual std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path); |
| 247 | 247 | ||
| 248 | // Deletes the subdirectory with name and returns true on success. | 248 | // Deletes the subdirectory with the given name and returns true on success. |
| 249 | virtual bool DeleteSubdirectory(std::string_view name) = 0; | 249 | virtual bool DeleteSubdirectory(std::string_view name) = 0; |
| 250 | // Deletes all subdirectories and files of subdirectory with name recirsively and then deletes | 250 | |
| 251 | // the subdirectory. Returns true on success. | 251 | // Deletes all subdirectories and files within the provided directory and then deletes |
| 252 | // the directory itself. Returns true on success. | ||
| 252 | virtual bool DeleteSubdirectoryRecursive(std::string_view name); | 253 | virtual bool DeleteSubdirectoryRecursive(std::string_view name); |
| 253 | // Returnes whether or not the file with name name was deleted successfully. | 254 | |
| 255 | // Deletes all subdirectories and files within the provided directory. | ||
| 256 | // Unlike DeleteSubdirectoryRecursive, this does not delete the provided directory. | ||
| 257 | virtual bool CleanSubdirectoryRecursive(std::string_view name); | ||
| 258 | |||
| 259 | // Returns whether or not the file with name name was deleted successfully. | ||
| 254 | virtual bool DeleteFile(std::string_view name) = 0; | 260 | virtual bool DeleteFile(std::string_view name) = 0; |
| 255 | 261 | ||
| 256 | // Returns whether or not this directory was renamed to name. | 262 | // Returns whether or not this directory was renamed to name. |
| @@ -276,7 +282,13 @@ public: | |||
| 276 | bool IsReadable() const override; | 282 | bool IsReadable() const override; |
| 277 | std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override; | 283 | std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override; |
| 278 | std::shared_ptr<VfsFile> CreateFile(std::string_view name) override; | 284 | std::shared_ptr<VfsFile> CreateFile(std::string_view name) override; |
| 285 | std::shared_ptr<VfsFile> CreateFileAbsolute(std::string_view path) override; | ||
| 286 | std::shared_ptr<VfsFile> CreateFileRelative(std::string_view path) override; | ||
| 287 | std::shared_ptr<VfsDirectory> CreateDirectoryAbsolute(std::string_view path) override; | ||
| 288 | std::shared_ptr<VfsDirectory> CreateDirectoryRelative(std::string_view path) override; | ||
| 279 | bool DeleteSubdirectory(std::string_view name) override; | 289 | bool DeleteSubdirectory(std::string_view name) override; |
| 290 | bool DeleteSubdirectoryRecursive(std::string_view name) override; | ||
| 291 | bool CleanSubdirectoryRecursive(std::string_view name) override; | ||
| 280 | bool DeleteFile(std::string_view name) override; | 292 | bool DeleteFile(std::string_view name) override; |
| 281 | bool Rename(std::string_view name) override; | 293 | bool Rename(std::string_view name) override; |
| 282 | }; | 294 | }; |
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 1bf79b692..c8acde5b1 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp | |||
| @@ -42,9 +42,10 @@ ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) { | |||
| 42 | u16 generation = next_generation++; | 42 | u16 generation = next_generation++; |
| 43 | 43 | ||
| 44 | // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. | 44 | // Overflow count so it fits in the 15 bits dedicated to the generation in the handle. |
| 45 | // CTR-OS doesn't use generation 0, so skip straight to 1. | 45 | // Horizon OS uses zero to represent an invalid handle, so skip to 1. |
| 46 | if (next_generation >= (1 << 15)) | 46 | if (next_generation >= (1 << 15)) { |
| 47 | next_generation = 1; | 47 | next_generation = 1; |
| 48 | } | ||
| 48 | 49 | ||
| 49 | generations[slot] = generation; | 50 | generations[slot] = generation; |
| 50 | objects[slot] = std::move(obj); | 51 | objects[slot] = std::move(obj); |
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index e3f3e3fb8..6b7927fd8 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | 14 | ||
| 15 | enum KernelHandle : Handle { | 15 | enum KernelHandle : Handle { |
| 16 | InvalidHandle = 0, | ||
| 16 | CurrentThread = 0xFFFF8000, | 17 | CurrentThread = 0xFFFF8000, |
| 17 | CurrentProcess = 0xFFFF8001, | 18 | CurrentProcess = 0xFFFF8001, |
| 18 | }; | 19 | }; |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 68d5376cb..61ce7d7e4 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -15,13 +15,14 @@ | |||
| 15 | #include "common/logging/log.h" | 15 | #include "common/logging/log.h" |
| 16 | #include "core/core.h" | 16 | #include "core/core.h" |
| 17 | #include "core/hle/ipc_helpers.h" | 17 | #include "core/hle/ipc_helpers.h" |
| 18 | #include "core/hle/kernel/event.h" | ||
| 19 | #include "core/hle/kernel/handle_table.h" | 18 | #include "core/hle/kernel/handle_table.h" |
| 20 | #include "core/hle/kernel/hle_ipc.h" | 19 | #include "core/hle/kernel/hle_ipc.h" |
| 21 | #include "core/hle/kernel/kernel.h" | 20 | #include "core/hle/kernel/kernel.h" |
| 22 | #include "core/hle/kernel/object.h" | 21 | #include "core/hle/kernel/object.h" |
| 23 | #include "core/hle/kernel/process.h" | 22 | #include "core/hle/kernel/process.h" |
| 23 | #include "core/hle/kernel/readable_event.h" | ||
| 24 | #include "core/hle/kernel/server_session.h" | 24 | #include "core/hle/kernel/server_session.h" |
| 25 | #include "core/hle/kernel/writable_event.h" | ||
| 25 | #include "core/memory.h" | 26 | #include "core/memory.h" |
| 26 | 27 | ||
| 27 | namespace Kernel { | 28 | namespace Kernel { |
| @@ -36,11 +37,9 @@ void SessionRequestHandler::ClientDisconnected(const SharedPtr<ServerSession>& s | |||
| 36 | boost::range::remove_erase(connected_sessions, server_session); | 37 | boost::range::remove_erase(connected_sessions, server_session); |
| 37 | } | 38 | } |
| 38 | 39 | ||
| 39 | SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread, | 40 | SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( |
| 40 | const std::string& reason, u64 timeout, | 41 | SharedPtr<Thread> thread, const std::string& reason, u64 timeout, WakeupCallback&& callback, |
| 41 | WakeupCallback&& callback, | 42 | SharedPtr<WritableEvent> writable_event) { |
| 42 | Kernel::SharedPtr<Kernel::Event> event) { | ||
| 43 | |||
| 44 | // Put the client thread to sleep until the wait event is signaled or the timeout expires. | 43 | // Put the client thread to sleep until the wait event is signaled or the timeout expires. |
| 45 | thread->SetWakeupCallback([context = *this, callback]( | 44 | thread->SetWakeupCallback([context = *this, callback]( |
| 46 | ThreadWakeupReason reason, SharedPtr<Thread> thread, | 45 | ThreadWakeupReason reason, SharedPtr<Thread> thread, |
| @@ -51,23 +50,25 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread, | |||
| 51 | return true; | 50 | return true; |
| 52 | }); | 51 | }); |
| 53 | 52 | ||
| 54 | if (!event) { | 53 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 54 | if (!writable_event) { | ||
| 55 | // Create event if not provided | 55 | // Create event if not provided |
| 56 | auto& kernel = Core::System::GetInstance().Kernel(); | 56 | const auto pair = WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, |
| 57 | event = | 57 | "HLE Pause Event: " + reason); |
| 58 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "HLE Pause Event: " + reason); | 58 | writable_event = pair.writable; |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | event->Clear(); | 61 | const auto readable_event{writable_event->GetReadableEvent()}; |
| 62 | writable_event->Clear(); | ||
| 62 | thread->SetStatus(ThreadStatus::WaitHLEEvent); | 63 | thread->SetStatus(ThreadStatus::WaitHLEEvent); |
| 63 | thread->SetWaitObjects({event}); | 64 | thread->SetWaitObjects({readable_event}); |
| 64 | event->AddWaitingThread(thread); | 65 | readable_event->AddWaitingThread(thread); |
| 65 | 66 | ||
| 66 | if (timeout > 0) { | 67 | if (timeout > 0) { |
| 67 | thread->WakeAfterDelay(timeout); | 68 | thread->WakeAfterDelay(timeout); |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | return event; | 71 | return writable_event; |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session) | 74 | HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_session) |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index a38e34b74..e5c0610cd 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -24,10 +24,11 @@ class ServiceFrameworkBase; | |||
| 24 | namespace Kernel { | 24 | namespace Kernel { |
| 25 | 25 | ||
| 26 | class Domain; | 26 | class Domain; |
| 27 | class Event; | ||
| 28 | class HandleTable; | 27 | class HandleTable; |
| 29 | class HLERequestContext; | 28 | class HLERequestContext; |
| 30 | class Process; | 29 | class Process; |
| 30 | class ReadableEvent; | ||
| 31 | class WritableEvent; | ||
| 31 | 32 | ||
| 32 | /** | 33 | /** |
| 33 | * Interface implemented by HLE Session handlers. | 34 | * Interface implemented by HLE Session handlers. |
| @@ -119,12 +120,13 @@ public: | |||
| 119 | * @param callback Callback to be invoked when the thread is resumed. This callback must write | 120 | * @param callback Callback to be invoked when the thread is resumed. This callback must write |
| 120 | * the entire command response once again, regardless of the state of it before this function | 121 | * the entire command response once again, regardless of the state of it before this function |
| 121 | * was called. | 122 | * was called. |
| 122 | * @param event Event to use to wake up the thread. If unspecified, an event will be created. | 123 | * @param writable_event Event to use to wake up the thread. If unspecified, an event will be |
| 124 | * created. | ||
| 123 | * @returns Event that when signaled will resume the thread and call the callback function. | 125 | * @returns Event that when signaled will resume the thread and call the callback function. |
| 124 | */ | 126 | */ |
| 125 | SharedPtr<Event> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason, | 127 | SharedPtr<WritableEvent> SleepClientThread(SharedPtr<Thread> thread, const std::string& reason, |
| 126 | u64 timeout, WakeupCallback&& callback, | 128 | u64 timeout, WakeupCallback&& callback, |
| 127 | Kernel::SharedPtr<Kernel::Event> event = nullptr); | 129 | SharedPtr<WritableEvent> writable_event = nullptr); |
| 128 | 130 | ||
| 129 | /// Populates this context with data from the requesting process/thread. | 131 | /// Populates this context with data from the requesting process/thread. |
| 130 | ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table, | 132 | ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table, |
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp index d87a62bb9..bb1b68778 100644 --- a/src/core/hle/kernel/object.cpp +++ b/src/core/hle/kernel/object.cpp | |||
| @@ -13,7 +13,7 @@ Object::~Object() = default; | |||
| 13 | 13 | ||
| 14 | bool Object::IsWaitable() const { | 14 | bool Object::IsWaitable() const { |
| 15 | switch (GetHandleType()) { | 15 | switch (GetHandleType()) { |
| 16 | case HandleType::Event: | 16 | case HandleType::ReadableEvent: |
| 17 | case HandleType::Thread: | 17 | case HandleType::Thread: |
| 18 | case HandleType::Timer: | 18 | case HandleType::Timer: |
| 19 | case HandleType::ServerPort: | 19 | case HandleType::ServerPort: |
| @@ -21,6 +21,7 @@ bool Object::IsWaitable() const { | |||
| 21 | return true; | 21 | return true; |
| 22 | 22 | ||
| 23 | case HandleType::Unknown: | 23 | case HandleType::Unknown: |
| 24 | case HandleType::WritableEvent: | ||
| 24 | case HandleType::SharedMemory: | 25 | case HandleType::SharedMemory: |
| 25 | case HandleType::Process: | 26 | case HandleType::Process: |
| 26 | case HandleType::AddressArbiter: | 27 | case HandleType::AddressArbiter: |
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index c9f4d0bb3..f1606a204 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h | |||
| @@ -19,7 +19,8 @@ using Handle = u32; | |||
| 19 | 19 | ||
| 20 | enum class HandleType : u32 { | 20 | enum class HandleType : u32 { |
| 21 | Unknown, | 21 | Unknown, |
| 22 | Event, | 22 | WritableEvent, |
| 23 | ReadableEvent, | ||
| 23 | SharedMemory, | 24 | SharedMemory, |
| 24 | Thread, | 25 | Thread, |
| 25 | Process, | 26 | Process, |
| @@ -33,9 +34,9 @@ enum class HandleType : u32 { | |||
| 33 | }; | 34 | }; |
| 34 | 35 | ||
| 35 | enum class ResetType { | 36 | enum class ResetType { |
| 36 | OneShot, | 37 | OneShot, ///< Reset automatically on object acquisition |
| 37 | Sticky, | 38 | Sticky, ///< Never reset automatically |
| 38 | Pulse, | 39 | Pulse, ///< Reset automatically on wakeup |
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| 41 | class Object : NonCopyable { | 42 | class Object : NonCopyable { |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 7ca538401..4ecb8c926 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -44,6 +44,10 @@ SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) { | |||
| 44 | return process; | 44 | return process; |
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | SharedPtr<ResourceLimit> Process::GetResourceLimit() const { | ||
| 48 | return resource_limit; | ||
| 49 | } | ||
| 50 | |||
| 47 | void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { | 51 | void Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) { |
| 48 | program_id = metadata.GetTitleID(); | 52 | program_id = metadata.GetTitleID(); |
| 49 | is_64bit_process = metadata.Is64BitProgram(); | 53 | is_64bit_process = metadata.Is64BitProgram(); |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index ada845c7f..49345aa66 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -171,14 +171,7 @@ public: | |||
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | /// Gets the resource limit descriptor for this process | 173 | /// Gets the resource limit descriptor for this process |
| 174 | ResourceLimit& GetResourceLimit() { | 174 | SharedPtr<ResourceLimit> GetResourceLimit() const; |
| 175 | return *resource_limit; | ||
| 176 | } | ||
| 177 | |||
| 178 | /// Gets the resource limit descriptor for this process | ||
| 179 | const ResourceLimit& GetResourceLimit() const { | ||
| 180 | return *resource_limit; | ||
| 181 | } | ||
| 182 | 175 | ||
| 183 | /// Gets the default CPU ID for this process | 176 | /// Gets the default CPU ID for this process |
| 184 | u8 GetDefaultProcessorID() const { | 177 | u8 GetDefaultProcessorID() const { |
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/readable_event.cpp index 8967e602e..92e16b4e6 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/readable_event.cpp | |||
| @@ -4,46 +4,37 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "core/hle/kernel/event.h" | ||
| 8 | #include "core/hle/kernel/object.h" | 7 | #include "core/hle/kernel/object.h" |
| 8 | #include "core/hle/kernel/readable_event.h" | ||
| 9 | #include "core/hle/kernel/thread.h" | 9 | #include "core/hle/kernel/thread.h" |
| 10 | #include "core/hle/kernel/writable_event.h" | ||
| 10 | 11 | ||
| 11 | namespace Kernel { | 12 | namespace Kernel { |
| 12 | 13 | ||
| 13 | Event::Event(KernelCore& kernel) : WaitObject{kernel} {} | 14 | ReadableEvent::ReadableEvent(KernelCore& kernel) : WaitObject{kernel} {} |
| 14 | Event::~Event() = default; | 15 | ReadableEvent::~ReadableEvent() = default; |
| 15 | 16 | ||
| 16 | SharedPtr<Event> Event::Create(KernelCore& kernel, ResetType reset_type, std::string name) { | 17 | bool ReadableEvent::ShouldWait(Thread* thread) const { |
| 17 | SharedPtr<Event> evt(new Event(kernel)); | ||
| 18 | |||
| 19 | evt->signaled = false; | ||
| 20 | evt->reset_type = reset_type; | ||
| 21 | evt->name = std::move(name); | ||
| 22 | |||
| 23 | return evt; | ||
| 24 | } | ||
| 25 | |||
| 26 | bool Event::ShouldWait(Thread* thread) const { | ||
| 27 | return !signaled; | 18 | return !signaled; |
| 28 | } | 19 | } |
| 29 | 20 | ||
| 30 | void Event::Acquire(Thread* thread) { | 21 | void ReadableEvent::Acquire(Thread* thread) { |
| 31 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); | 22 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); |
| 32 | 23 | ||
| 33 | if (reset_type == ResetType::OneShot) | 24 | if (reset_type == ResetType::OneShot) |
| 34 | signaled = false; | 25 | signaled = false; |
| 35 | } | 26 | } |
| 36 | 27 | ||
| 37 | void Event::Signal() { | 28 | void ReadableEvent::Signal() { |
| 38 | signaled = true; | 29 | signaled = true; |
| 39 | WakeupAllWaitingThreads(); | 30 | WakeupAllWaitingThreads(); |
| 40 | } | 31 | } |
| 41 | 32 | ||
| 42 | void Event::Clear() { | 33 | void ReadableEvent::Clear() { |
| 43 | signaled = false; | 34 | signaled = false; |
| 44 | } | 35 | } |
| 45 | 36 | ||
| 46 | void Event::WakeupAllWaitingThreads() { | 37 | void ReadableEvent::WakeupAllWaitingThreads() { |
| 47 | WaitObject::WakeupAllWaitingThreads(); | 38 | WaitObject::WakeupAllWaitingThreads(); |
| 48 | 39 | ||
| 49 | if (reset_type == ResetType::Pulse) | 40 | if (reset_type == ResetType::Pulse) |
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h new file mode 100644 index 000000000..867ff3051 --- /dev/null +++ b/src/core/hle/kernel/readable_event.h | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | // Copyright 2014 Citra 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 "core/hle/kernel/object.h" | ||
| 8 | #include "core/hle/kernel/wait_object.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | class KernelCore; | ||
| 13 | class WritableEvent; | ||
| 14 | |||
| 15 | class ReadableEvent final : public WaitObject { | ||
| 16 | friend class WritableEvent; | ||
| 17 | |||
| 18 | public: | ||
| 19 | ~ReadableEvent() override; | ||
| 20 | |||
| 21 | std::string GetTypeName() const override { | ||
| 22 | return "ReadableEvent"; | ||
| 23 | } | ||
| 24 | std::string GetName() const override { | ||
| 25 | return name; | ||
| 26 | } | ||
| 27 | |||
| 28 | ResetType GetResetType() const { | ||
| 29 | return reset_type; | ||
| 30 | } | ||
| 31 | |||
| 32 | static const HandleType HANDLE_TYPE = HandleType::ReadableEvent; | ||
| 33 | HandleType GetHandleType() const override { | ||
| 34 | return HANDLE_TYPE; | ||
| 35 | } | ||
| 36 | |||
| 37 | bool ShouldWait(Thread* thread) const override; | ||
| 38 | void Acquire(Thread* thread) override; | ||
| 39 | |||
| 40 | void WakeupAllWaitingThreads() override; | ||
| 41 | |||
| 42 | void Clear(); | ||
| 43 | |||
| 44 | private: | ||
| 45 | explicit ReadableEvent(KernelCore& kernel); | ||
| 46 | |||
| 47 | void Signal(); | ||
| 48 | |||
| 49 | ResetType reset_type; | ||
| 50 | bool signaled; | ||
| 51 | |||
| 52 | std::string name; ///< Name of event (optional) | ||
| 53 | }; | ||
| 54 | |||
| 55 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 3339777c1..e6c77f9db 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -20,21 +20,21 @@ | |||
| 20 | #include "core/hle/kernel/address_arbiter.h" | 20 | #include "core/hle/kernel/address_arbiter.h" |
| 21 | #include "core/hle/kernel/client_port.h" | 21 | #include "core/hle/kernel/client_port.h" |
| 22 | #include "core/hle/kernel/client_session.h" | 22 | #include "core/hle/kernel/client_session.h" |
| 23 | #include "core/hle/kernel/event.h" | ||
| 24 | #include "core/hle/kernel/handle_table.h" | 23 | #include "core/hle/kernel/handle_table.h" |
| 25 | #include "core/hle/kernel/kernel.h" | 24 | #include "core/hle/kernel/kernel.h" |
| 26 | #include "core/hle/kernel/mutex.h" | 25 | #include "core/hle/kernel/mutex.h" |
| 27 | #include "core/hle/kernel/process.h" | 26 | #include "core/hle/kernel/process.h" |
| 27 | #include "core/hle/kernel/readable_event.h" | ||
| 28 | #include "core/hle/kernel/resource_limit.h" | 28 | #include "core/hle/kernel/resource_limit.h" |
| 29 | #include "core/hle/kernel/scheduler.h" | 29 | #include "core/hle/kernel/scheduler.h" |
| 30 | #include "core/hle/kernel/shared_memory.h" | 30 | #include "core/hle/kernel/shared_memory.h" |
| 31 | #include "core/hle/kernel/svc.h" | 31 | #include "core/hle/kernel/svc.h" |
| 32 | #include "core/hle/kernel/svc_wrap.h" | 32 | #include "core/hle/kernel/svc_wrap.h" |
| 33 | #include "core/hle/kernel/thread.h" | 33 | #include "core/hle/kernel/thread.h" |
| 34 | #include "core/hle/kernel/writable_event.h" | ||
| 34 | #include "core/hle/lock.h" | 35 | #include "core/hle/lock.h" |
| 35 | #include "core/hle/result.h" | 36 | #include "core/hle/result.h" |
| 36 | #include "core/hle/service/service.h" | 37 | #include "core/hle/service/service.h" |
| 37 | #include "core/settings.h" | ||
| 38 | 38 | ||
| 39 | namespace Kernel { | 39 | namespace Kernel { |
| 40 | namespace { | 40 | namespace { |
| @@ -662,7 +662,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 662 | TotalMemoryUsage = 6, | 662 | TotalMemoryUsage = 6, |
| 663 | TotalHeapUsage = 7, | 663 | TotalHeapUsage = 7, |
| 664 | IsCurrentProcessBeingDebugged = 8, | 664 | IsCurrentProcessBeingDebugged = 8, |
| 665 | ResourceHandleLimit = 9, | 665 | RegisterResourceLimit = 9, |
| 666 | IdleTickCount = 10, | 666 | IdleTickCount = 10, |
| 667 | RandomEntropy = 11, | 667 | RandomEntropy = 11, |
| 668 | PerformanceCounter = 0xF0000002, | 668 | PerformanceCounter = 0xF0000002, |
| @@ -682,37 +682,137 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 682 | ThreadTickCount = 0xF0000002, | 682 | ThreadTickCount = 0xF0000002, |
| 683 | }; | 683 | }; |
| 684 | 684 | ||
| 685 | const auto* current_process = Core::CurrentProcess(); | 685 | const auto info_id_type = static_cast<GetInfoType>(info_id); |
| 686 | const auto& vm_manager = current_process->VMManager(); | ||
| 687 | 686 | ||
| 688 | switch (static_cast<GetInfoType>(info_id)) { | 687 | switch (info_id_type) { |
| 689 | case GetInfoType::AllowedCpuIdBitmask: | 688 | case GetInfoType::AllowedCpuIdBitmask: |
| 690 | *result = current_process->GetAllowedProcessorMask(); | ||
| 691 | break; | ||
| 692 | case GetInfoType::AllowedThreadPrioBitmask: | 689 | case GetInfoType::AllowedThreadPrioBitmask: |
| 693 | *result = current_process->GetAllowedThreadPriorityMask(); | ||
| 694 | break; | ||
| 695 | case GetInfoType::MapRegionBaseAddr: | 690 | case GetInfoType::MapRegionBaseAddr: |
| 696 | *result = vm_manager.GetMapRegionBaseAddress(); | ||
| 697 | break; | ||
| 698 | case GetInfoType::MapRegionSize: | 691 | case GetInfoType::MapRegionSize: |
| 699 | *result = vm_manager.GetMapRegionSize(); | ||
| 700 | break; | ||
| 701 | case GetInfoType::HeapRegionBaseAddr: | 692 | case GetInfoType::HeapRegionBaseAddr: |
| 702 | *result = vm_manager.GetHeapRegionBaseAddress(); | ||
| 703 | break; | ||
| 704 | case GetInfoType::HeapRegionSize: | 693 | case GetInfoType::HeapRegionSize: |
| 705 | *result = vm_manager.GetHeapRegionSize(); | 694 | case GetInfoType::ASLRRegionBaseAddr: |
| 706 | break; | 695 | case GetInfoType::ASLRRegionSize: |
| 696 | case GetInfoType::NewMapRegionBaseAddr: | ||
| 697 | case GetInfoType::NewMapRegionSize: | ||
| 707 | case GetInfoType::TotalMemoryUsage: | 698 | case GetInfoType::TotalMemoryUsage: |
| 708 | *result = vm_manager.GetTotalMemoryUsage(); | ||
| 709 | break; | ||
| 710 | case GetInfoType::TotalHeapUsage: | 699 | case GetInfoType::TotalHeapUsage: |
| 711 | *result = vm_manager.GetTotalHeapUsage(); | 700 | case GetInfoType::IsVirtualAddressMemoryEnabled: |
| 712 | break; | 701 | case GetInfoType::PersonalMmHeapUsage: |
| 702 | case GetInfoType::TitleId: | ||
| 703 | case GetInfoType::UserExceptionContextAddr: { | ||
| 704 | if (info_sub_id != 0) { | ||
| 705 | return ERR_INVALID_ENUM_VALUE; | ||
| 706 | } | ||
| 707 | |||
| 708 | const auto& current_process_handle_table = Core::CurrentProcess()->GetHandleTable(); | ||
| 709 | const auto process = current_process_handle_table.Get<Process>(static_cast<Handle>(handle)); | ||
| 710 | if (!process) { | ||
| 711 | return ERR_INVALID_HANDLE; | ||
| 712 | } | ||
| 713 | |||
| 714 | switch (info_id_type) { | ||
| 715 | case GetInfoType::AllowedCpuIdBitmask: | ||
| 716 | *result = process->GetAllowedProcessorMask(); | ||
| 717 | return RESULT_SUCCESS; | ||
| 718 | |||
| 719 | case GetInfoType::AllowedThreadPrioBitmask: | ||
| 720 | *result = process->GetAllowedThreadPriorityMask(); | ||
| 721 | return RESULT_SUCCESS; | ||
| 722 | |||
| 723 | case GetInfoType::MapRegionBaseAddr: | ||
| 724 | *result = process->VMManager().GetMapRegionBaseAddress(); | ||
| 725 | return RESULT_SUCCESS; | ||
| 726 | |||
| 727 | case GetInfoType::MapRegionSize: | ||
| 728 | *result = process->VMManager().GetMapRegionSize(); | ||
| 729 | return RESULT_SUCCESS; | ||
| 730 | |||
| 731 | case GetInfoType::HeapRegionBaseAddr: | ||
| 732 | *result = process->VMManager().GetHeapRegionBaseAddress(); | ||
| 733 | return RESULT_SUCCESS; | ||
| 734 | |||
| 735 | case GetInfoType::HeapRegionSize: | ||
| 736 | *result = process->VMManager().GetHeapRegionSize(); | ||
| 737 | return RESULT_SUCCESS; | ||
| 738 | |||
| 739 | case GetInfoType::ASLRRegionBaseAddr: | ||
| 740 | *result = process->VMManager().GetASLRRegionBaseAddress(); | ||
| 741 | return RESULT_SUCCESS; | ||
| 742 | |||
| 743 | case GetInfoType::ASLRRegionSize: | ||
| 744 | *result = process->VMManager().GetASLRRegionSize(); | ||
| 745 | return RESULT_SUCCESS; | ||
| 746 | |||
| 747 | case GetInfoType::NewMapRegionBaseAddr: | ||
| 748 | *result = process->VMManager().GetNewMapRegionBaseAddress(); | ||
| 749 | return RESULT_SUCCESS; | ||
| 750 | |||
| 751 | case GetInfoType::NewMapRegionSize: | ||
| 752 | *result = process->VMManager().GetNewMapRegionSize(); | ||
| 753 | return RESULT_SUCCESS; | ||
| 754 | |||
| 755 | case GetInfoType::TotalMemoryUsage: | ||
| 756 | *result = process->VMManager().GetTotalMemoryUsage(); | ||
| 757 | return RESULT_SUCCESS; | ||
| 758 | |||
| 759 | case GetInfoType::TotalHeapUsage: | ||
| 760 | *result = process->VMManager().GetTotalHeapUsage(); | ||
| 761 | return RESULT_SUCCESS; | ||
| 762 | |||
| 763 | case GetInfoType::IsVirtualAddressMemoryEnabled: | ||
| 764 | *result = process->IsVirtualMemoryEnabled(); | ||
| 765 | return RESULT_SUCCESS; | ||
| 766 | |||
| 767 | case GetInfoType::TitleId: | ||
| 768 | *result = process->GetTitleID(); | ||
| 769 | return RESULT_SUCCESS; | ||
| 770 | |||
| 771 | case GetInfoType::UserExceptionContextAddr: | ||
| 772 | LOG_WARNING(Kernel_SVC, | ||
| 773 | "(STUBBED) Attempted to query user exception context address, returned 0"); | ||
| 774 | *result = 0; | ||
| 775 | return RESULT_SUCCESS; | ||
| 776 | |||
| 777 | default: | ||
| 778 | break; | ||
| 779 | } | ||
| 780 | |||
| 781 | LOG_WARNING(Kernel_SVC, "(STUBBED) Unimplemented svcGetInfo id=0x{:016X}", info_id); | ||
| 782 | return ERR_INVALID_ENUM_VALUE; | ||
| 783 | } | ||
| 784 | |||
| 713 | case GetInfoType::IsCurrentProcessBeingDebugged: | 785 | case GetInfoType::IsCurrentProcessBeingDebugged: |
| 714 | *result = 0; | 786 | *result = 0; |
| 715 | break; | 787 | return RESULT_SUCCESS; |
| 788 | |||
| 789 | case GetInfoType::RegisterResourceLimit: { | ||
| 790 | if (handle != 0) { | ||
| 791 | return ERR_INVALID_HANDLE; | ||
| 792 | } | ||
| 793 | |||
| 794 | if (info_sub_id != 0) { | ||
| 795 | return ERR_INVALID_COMBINATION; | ||
| 796 | } | ||
| 797 | |||
| 798 | Process* const current_process = Core::CurrentProcess(); | ||
| 799 | HandleTable& handle_table = current_process->GetHandleTable(); | ||
| 800 | const auto resource_limit = current_process->GetResourceLimit(); | ||
| 801 | if (!resource_limit) { | ||
| 802 | *result = KernelHandle::InvalidHandle; | ||
| 803 | // Yes, the kernel considers this a successful operation. | ||
| 804 | return RESULT_SUCCESS; | ||
| 805 | } | ||
| 806 | |||
| 807 | const auto table_result = handle_table.Create(resource_limit); | ||
| 808 | if (table_result.Failed()) { | ||
| 809 | return table_result.Code(); | ||
| 810 | } | ||
| 811 | |||
| 812 | *result = *table_result; | ||
| 813 | return RESULT_SUCCESS; | ||
| 814 | } | ||
| 815 | |||
| 716 | case GetInfoType::RandomEntropy: | 816 | case GetInfoType::RandomEntropy: |
| 717 | if (handle != 0) { | 817 | if (handle != 0) { |
| 718 | LOG_ERROR(Kernel_SVC, "Process Handle is non zero, expected 0 result but got {:016X}", | 818 | LOG_ERROR(Kernel_SVC, "Process Handle is non zero, expected 0 result but got {:016X}", |
| @@ -726,37 +826,15 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 726 | return ERR_INVALID_COMBINATION; | 826 | return ERR_INVALID_COMBINATION; |
| 727 | } | 827 | } |
| 728 | 828 | ||
| 729 | *result = current_process->GetRandomEntropy(info_sub_id); | 829 | *result = Core::CurrentProcess()->GetRandomEntropy(info_sub_id); |
| 730 | return RESULT_SUCCESS; | 830 | return RESULT_SUCCESS; |
| 731 | break; | 831 | |
| 732 | case GetInfoType::ASLRRegionBaseAddr: | ||
| 733 | *result = vm_manager.GetASLRRegionBaseAddress(); | ||
| 734 | break; | ||
| 735 | case GetInfoType::ASLRRegionSize: | ||
| 736 | *result = vm_manager.GetASLRRegionSize(); | ||
| 737 | break; | ||
| 738 | case GetInfoType::NewMapRegionBaseAddr: | ||
| 739 | *result = vm_manager.GetNewMapRegionBaseAddress(); | ||
| 740 | break; | ||
| 741 | case GetInfoType::NewMapRegionSize: | ||
| 742 | *result = vm_manager.GetNewMapRegionSize(); | ||
| 743 | break; | ||
| 744 | case GetInfoType::IsVirtualAddressMemoryEnabled: | ||
| 745 | *result = current_process->IsVirtualMemoryEnabled(); | ||
| 746 | break; | ||
| 747 | case GetInfoType::TitleId: | ||
| 748 | *result = current_process->GetTitleID(); | ||
| 749 | break; | ||
| 750 | case GetInfoType::PrivilegedProcessId: | 832 | case GetInfoType::PrivilegedProcessId: |
| 751 | LOG_WARNING(Kernel_SVC, | 833 | LOG_WARNING(Kernel_SVC, |
| 752 | "(STUBBED) Attempted to query privileged process id bounds, returned 0"); | 834 | "(STUBBED) Attempted to query privileged process id bounds, returned 0"); |
| 753 | *result = 0; | 835 | *result = 0; |
| 754 | break; | 836 | return RESULT_SUCCESS; |
| 755 | case GetInfoType::UserExceptionContextAddr: | 837 | |
| 756 | LOG_WARNING(Kernel_SVC, | ||
| 757 | "(STUBBED) Attempted to query user exception context address, returned 0"); | ||
| 758 | *result = 0; | ||
| 759 | break; | ||
| 760 | case GetInfoType::ThreadTickCount: { | 838 | case GetInfoType::ThreadTickCount: { |
| 761 | constexpr u64 num_cpus = 4; | 839 | constexpr u64 num_cpus = 4; |
| 762 | if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) { | 840 | if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) { |
| @@ -766,7 +844,7 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 766 | } | 844 | } |
| 767 | 845 | ||
| 768 | const auto thread = | 846 | const auto thread = |
| 769 | current_process->GetHandleTable().Get<Thread>(static_cast<Handle>(handle)); | 847 | Core::CurrentProcess()->GetHandleTable().Get<Thread>(static_cast<Handle>(handle)); |
| 770 | if (!thread) { | 848 | if (!thread) { |
| 771 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", | 849 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", |
| 772 | static_cast<Handle>(handle)); | 850 | static_cast<Handle>(handle)); |
| @@ -789,14 +867,13 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | |||
| 789 | } | 867 | } |
| 790 | 868 | ||
| 791 | *result = out_ticks; | 869 | *result = out_ticks; |
| 792 | break; | 870 | return RESULT_SUCCESS; |
| 793 | } | 871 | } |
| 872 | |||
| 794 | default: | 873 | default: |
| 795 | LOG_WARNING(Kernel_SVC, "(STUBBED) Unimplemented svcGetInfo id=0x{:016X}", info_id); | 874 | LOG_WARNING(Kernel_SVC, "(STUBBED) Unimplemented svcGetInfo id=0x{:016X}", info_id); |
| 796 | return ERR_INVALID_ENUM_VALUE; | 875 | return ERR_INVALID_ENUM_VALUE; |
| 797 | } | 876 | } |
| 798 | |||
| 799 | return RESULT_SUCCESS; | ||
| 800 | } | 877 | } |
| 801 | 878 | ||
| 802 | /// Sets the thread activity | 879 | /// Sets the thread activity |
| @@ -1042,7 +1119,7 @@ static void ExitProcess() { | |||
| 1042 | static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top, | 1119 | static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top, |
| 1043 | u32 priority, s32 processor_id) { | 1120 | u32 priority, s32 processor_id) { |
| 1044 | LOG_TRACE(Kernel_SVC, | 1121 | LOG_TRACE(Kernel_SVC, |
| 1045 | "called entrypoint=0x{:08X} ({}), arg=0x{:08X}, stacktop=0x{:08X}, " | 1122 | "called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, " |
| 1046 | "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}", | 1123 | "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}", |
| 1047 | entry_point, arg, stack_top, priority, processor_id, *out_handle); | 1124 | entry_point, arg, stack_top, priority, processor_id, *out_handle); |
| 1048 | 1125 | ||
| @@ -1361,7 +1438,7 @@ static ResultCode ResetSignal(Handle handle) { | |||
| 1361 | LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); | 1438 | LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle); |
| 1362 | 1439 | ||
| 1363 | const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); | 1440 | const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); |
| 1364 | auto event = handle_table.Get<Event>(handle); | 1441 | auto event = handle_table.Get<ReadableEvent>(handle); |
| 1365 | 1442 | ||
| 1366 | ASSERT(event != nullptr); | 1443 | ASSERT(event != nullptr); |
| 1367 | 1444 | ||
| @@ -1520,17 +1597,67 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss | |||
| 1520 | return RESULT_SUCCESS; | 1597 | return RESULT_SUCCESS; |
| 1521 | } | 1598 | } |
| 1522 | 1599 | ||
| 1600 | static ResultCode CreateEvent(Handle* write_handle, Handle* read_handle) { | ||
| 1601 | LOG_DEBUG(Kernel_SVC, "called"); | ||
| 1602 | |||
| 1603 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 1604 | const auto [readable_event, writable_event] = | ||
| 1605 | WritableEvent::CreateEventPair(kernel, ResetType::Sticky, "CreateEvent"); | ||
| 1606 | |||
| 1607 | HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); | ||
| 1608 | |||
| 1609 | const auto write_create_result = handle_table.Create(writable_event); | ||
| 1610 | if (write_create_result.Failed()) { | ||
| 1611 | return write_create_result.Code(); | ||
| 1612 | } | ||
| 1613 | *write_handle = *write_create_result; | ||
| 1614 | |||
| 1615 | const auto read_create_result = handle_table.Create(readable_event); | ||
| 1616 | if (read_create_result.Failed()) { | ||
| 1617 | handle_table.Close(*write_create_result); | ||
| 1618 | return read_create_result.Code(); | ||
| 1619 | } | ||
| 1620 | *read_handle = *read_create_result; | ||
| 1621 | |||
| 1622 | LOG_DEBUG(Kernel_SVC, | ||
| 1623 | "successful. Writable event handle=0x{:08X}, Readable event handle=0x{:08X}", | ||
| 1624 | *write_create_result, *read_create_result); | ||
| 1625 | return RESULT_SUCCESS; | ||
| 1626 | } | ||
| 1627 | |||
| 1523 | static ResultCode ClearEvent(Handle handle) { | 1628 | static ResultCode ClearEvent(Handle handle) { |
| 1524 | LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); | 1629 | LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); |
| 1525 | 1630 | ||
| 1526 | const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); | 1631 | const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); |
| 1527 | SharedPtr<Event> evt = handle_table.Get<Event>(handle); | 1632 | |
| 1528 | if (evt == nullptr) { | 1633 | auto writable_event = handle_table.Get<WritableEvent>(handle); |
| 1529 | LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); | 1634 | if (writable_event) { |
| 1635 | writable_event->Clear(); | ||
| 1636 | return RESULT_SUCCESS; | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | auto readable_event = handle_table.Get<ReadableEvent>(handle); | ||
| 1640 | if (readable_event) { | ||
| 1641 | readable_event->Clear(); | ||
| 1642 | return RESULT_SUCCESS; | ||
| 1643 | } | ||
| 1644 | |||
| 1645 | LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); | ||
| 1646 | return ERR_INVALID_HANDLE; | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | static ResultCode SignalEvent(Handle handle) { | ||
| 1650 | LOG_DEBUG(Kernel_SVC, "called. Handle=0x{:08X}", handle); | ||
| 1651 | |||
| 1652 | HandleTable& handle_table = Core::CurrentProcess()->GetHandleTable(); | ||
| 1653 | auto writable_event = handle_table.Get<WritableEvent>(handle); | ||
| 1654 | |||
| 1655 | if (!writable_event) { | ||
| 1656 | LOG_ERROR(Kernel_SVC, "Non-existent writable event handle used (0x{:08X})", handle); | ||
| 1530 | return ERR_INVALID_HANDLE; | 1657 | return ERR_INVALID_HANDLE; |
| 1531 | } | 1658 | } |
| 1532 | 1659 | ||
| 1533 | evt->Clear(); | 1660 | writable_event->Signal(); |
| 1534 | return RESULT_SUCCESS; | 1661 | return RESULT_SUCCESS; |
| 1535 | } | 1662 | } |
| 1536 | 1663 | ||
| @@ -1669,7 +1796,7 @@ static const FunctionDef SVC_Table[] = { | |||
| 1669 | {0x0E, SvcWrap<GetThreadCoreMask>, "GetThreadCoreMask"}, | 1796 | {0x0E, SvcWrap<GetThreadCoreMask>, "GetThreadCoreMask"}, |
| 1670 | {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, | 1797 | {0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"}, |
| 1671 | {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, | 1798 | {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"}, |
| 1672 | {0x11, nullptr, "SignalEvent"}, | 1799 | {0x11, SvcWrap<SignalEvent>, "SignalEvent"}, |
| 1673 | {0x12, SvcWrap<ClearEvent>, "ClearEvent"}, | 1800 | {0x12, SvcWrap<ClearEvent>, "ClearEvent"}, |
| 1674 | {0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"}, | 1801 | {0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"}, |
| 1675 | {0x14, SvcWrap<UnmapSharedMemory>, "UnmapSharedMemory"}, | 1802 | {0x14, SvcWrap<UnmapSharedMemory>, "UnmapSharedMemory"}, |
| @@ -1721,7 +1848,7 @@ static const FunctionDef SVC_Table[] = { | |||
| 1721 | {0x42, nullptr, "ReplyAndReceiveLight"}, | 1848 | {0x42, nullptr, "ReplyAndReceiveLight"}, |
| 1722 | {0x43, nullptr, "ReplyAndReceive"}, | 1849 | {0x43, nullptr, "ReplyAndReceive"}, |
| 1723 | {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"}, | 1850 | {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"}, |
| 1724 | {0x45, nullptr, "CreateEvent"}, | 1851 | {0x45, SvcWrap<CreateEvent>, "CreateEvent"}, |
| 1725 | {0x46, nullptr, "Unknown"}, | 1852 | {0x46, nullptr, "Unknown"}, |
| 1726 | {0x47, nullptr, "Unknown"}, | 1853 | {0x47, nullptr, "Unknown"}, |
| 1727 | {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, | 1854 | {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, |
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index fa1116624..24aef46c9 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h | |||
| @@ -59,6 +59,19 @@ void SvcWrap() { | |||
| 59 | FuncReturn(retval); | 59 | FuncReturn(retval); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | template <ResultCode func(u32*, u32*)> | ||
| 63 | void SvcWrap() { | ||
| 64 | u32 param_1 = 0; | ||
| 65 | u32 param_2 = 0; | ||
| 66 | const u32 retval = func(¶m_1, ¶m_2).raw; | ||
| 67 | |||
| 68 | auto& arm_interface = Core::CurrentArmInterface(); | ||
| 69 | arm_interface.SetReg(1, param_1); | ||
| 70 | arm_interface.SetReg(2, param_2); | ||
| 71 | |||
| 72 | FuncReturn(retval); | ||
| 73 | } | ||
| 74 | |||
| 62 | template <ResultCode func(u32*, u64)> | 75 | template <ResultCode func(u32*, u64)> |
| 63 | void SvcWrap() { | 76 | void SvcWrap() { |
| 64 | u32 param_1 = 0; | 77 | u32 param_1 = 0; |
diff --git a/src/core/hle/kernel/writable_event.cpp b/src/core/hle/kernel/writable_event.cpp new file mode 100644 index 000000000..a58ea6ec8 --- /dev/null +++ b/src/core/hle/kernel/writable_event.cpp | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include "common/assert.h" | ||
| 7 | #include "core/hle/kernel/kernel.h" | ||
| 8 | #include "core/hle/kernel/object.h" | ||
| 9 | #include "core/hle/kernel/readable_event.h" | ||
| 10 | #include "core/hle/kernel/thread.h" | ||
| 11 | #include "core/hle/kernel/writable_event.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | WritableEvent::WritableEvent(KernelCore& kernel) : Object{kernel} {} | ||
| 16 | WritableEvent::~WritableEvent() = default; | ||
| 17 | |||
| 18 | EventPair WritableEvent::CreateEventPair(KernelCore& kernel, ResetType reset_type, | ||
| 19 | std::string name) { | ||
| 20 | SharedPtr<WritableEvent> writable_event(new WritableEvent(kernel)); | ||
| 21 | SharedPtr<ReadableEvent> readable_event(new ReadableEvent(kernel)); | ||
| 22 | |||
| 23 | writable_event->name = name + ":Writable"; | ||
| 24 | writable_event->readable = readable_event; | ||
| 25 | readable_event->name = name + ":Readable"; | ||
| 26 | readable_event->signaled = false; | ||
| 27 | readable_event->reset_type = reset_type; | ||
| 28 | |||
| 29 | return {std::move(readable_event), std::move(writable_event)}; | ||
| 30 | } | ||
| 31 | |||
| 32 | SharedPtr<ReadableEvent> WritableEvent::GetReadableEvent() const { | ||
| 33 | return readable; | ||
| 34 | } | ||
| 35 | |||
| 36 | ResetType WritableEvent::GetResetType() const { | ||
| 37 | return readable->reset_type; | ||
| 38 | } | ||
| 39 | |||
| 40 | void WritableEvent::Signal() { | ||
| 41 | readable->Signal(); | ||
| 42 | } | ||
| 43 | |||
| 44 | void WritableEvent::Clear() { | ||
| 45 | readable->Clear(); | ||
| 46 | } | ||
| 47 | |||
| 48 | bool WritableEvent::IsSignaled() const { | ||
| 49 | return readable->signaled; | ||
| 50 | } | ||
| 51 | |||
| 52 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/writable_event.h index 27d6126b0..8fa8d68ee 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/writable_event.h | |||
| @@ -11,49 +11,52 @@ | |||
| 11 | namespace Kernel { | 11 | namespace Kernel { |
| 12 | 12 | ||
| 13 | class KernelCore; | 13 | class KernelCore; |
| 14 | class ReadableEvent; | ||
| 15 | class WritableEvent; | ||
| 14 | 16 | ||
| 15 | class Event final : public WaitObject { | 17 | struct EventPair { |
| 18 | SharedPtr<ReadableEvent> readable; | ||
| 19 | SharedPtr<WritableEvent> writable; | ||
| 20 | }; | ||
| 21 | |||
| 22 | class WritableEvent final : public Object { | ||
| 16 | public: | 23 | public: |
| 24 | ~WritableEvent() override; | ||
| 25 | |||
| 17 | /** | 26 | /** |
| 18 | * Creates an event | 27 | * Creates an event |
| 19 | * @param kernel The kernel instance to create this event under. | 28 | * @param kernel The kernel instance to create this event under. |
| 20 | * @param reset_type ResetType describing how to create event | 29 | * @param reset_type ResetType describing how to create event |
| 21 | * @param name Optional name of event | 30 | * @param name Optional name of event |
| 22 | */ | 31 | */ |
| 23 | static SharedPtr<Event> Create(KernelCore& kernel, ResetType reset_type, | 32 | static EventPair CreateEventPair(KernelCore& kernel, ResetType reset_type, |
| 24 | std::string name = "Unknown"); | 33 | std::string name = "Unknown"); |
| 25 | 34 | ||
| 26 | std::string GetTypeName() const override { | 35 | std::string GetTypeName() const override { |
| 27 | return "Event"; | 36 | return "WritableEvent"; |
| 28 | } | 37 | } |
| 29 | std::string GetName() const override { | 38 | std::string GetName() const override { |
| 30 | return name; | 39 | return name; |
| 31 | } | 40 | } |
| 32 | 41 | ||
| 33 | static const HandleType HANDLE_TYPE = HandleType::Event; | 42 | static const HandleType HANDLE_TYPE = HandleType::WritableEvent; |
| 34 | HandleType GetHandleType() const override { | 43 | HandleType GetHandleType() const override { |
| 35 | return HANDLE_TYPE; | 44 | return HANDLE_TYPE; |
| 36 | } | 45 | } |
| 37 | 46 | ||
| 38 | ResetType GetResetType() const { | 47 | SharedPtr<ReadableEvent> GetReadableEvent() const; |
| 39 | return reset_type; | ||
| 40 | } | ||
| 41 | |||
| 42 | bool ShouldWait(Thread* thread) const override; | ||
| 43 | void Acquire(Thread* thread) override; | ||
| 44 | 48 | ||
| 45 | void WakeupAllWaitingThreads() override; | 49 | ResetType GetResetType() const; |
| 46 | 50 | ||
| 47 | void Signal(); | 51 | void Signal(); |
| 48 | void Clear(); | 52 | void Clear(); |
| 53 | bool IsSignaled() const; | ||
| 49 | 54 | ||
| 50 | private: | 55 | private: |
| 51 | explicit Event(KernelCore& kernel); | 56 | explicit WritableEvent(KernelCore& kernel); |
| 52 | ~Event() override; | ||
| 53 | 57 | ||
| 54 | ResetType reset_type; ///< Current ResetType | 58 | SharedPtr<ReadableEvent> readable; |
| 55 | 59 | ||
| 56 | bool signaled; ///< Whether the event has already been signaled | ||
| 57 | std::string name; ///< Name of event (optional) | 60 | std::string name; ///< Name of event (optional) |
| 58 | }; | 61 | }; |
| 59 | 62 | ||
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index d595c37b0..3a7b6da84 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -9,9 +9,11 @@ | |||
| 9 | #include "audio_core/audio_renderer.h" | 9 | #include "audio_core/audio_renderer.h" |
| 10 | #include "core/core.h" | 10 | #include "core/core.h" |
| 11 | #include "core/hle/ipc_helpers.h" | 11 | #include "core/hle/ipc_helpers.h" |
| 12 | #include "core/hle/kernel/event.h" | 12 | #include "core/hle/kernel/kernel.h" |
| 13 | #include "core/hle/kernel/process.h" | 13 | #include "core/hle/kernel/process.h" |
| 14 | #include "core/hle/kernel/readable_event.h" | ||
| 14 | #include "core/hle/kernel/shared_memory.h" | 15 | #include "core/hle/kernel/shared_memory.h" |
| 16 | #include "core/hle/kernel/writable_event.h" | ||
| 15 | #include "core/hle/service/acc/profile_manager.h" | 17 | #include "core/hle/service/acc/profile_manager.h" |
| 16 | #include "core/hle/service/am/am.h" | 18 | #include "core/hle/service/am/am.h" |
| 17 | #include "core/hle/service/am/applet_ae.h" | 19 | #include "core/hle/service/am/applet_ae.h" |
| @@ -208,8 +210,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger | |||
| 208 | RegisterHandlers(functions); | 210 | RegisterHandlers(functions); |
| 209 | 211 | ||
| 210 | auto& kernel = Core::System::GetInstance().Kernel(); | 212 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 211 | launchable_event = | 213 | launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, |
| 212 | Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent"); | 214 | "ISelfController:LaunchableEvent"); |
| 213 | } | 215 | } |
| 214 | 216 | ||
| 215 | ISelfController::~ISelfController() = default; | 217 | ISelfController::~ISelfController() = default; |
| @@ -295,11 +297,11 @@ void ISelfController::UnlockExit(Kernel::HLERequestContext& ctx) { | |||
| 295 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { | 297 | void ISelfController::GetLibraryAppletLaunchableEvent(Kernel::HLERequestContext& ctx) { |
| 296 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 298 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 297 | 299 | ||
| 298 | launchable_event->Signal(); | 300 | launchable_event.writable->Signal(); |
| 299 | 301 | ||
| 300 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 302 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 301 | rb.Push(RESULT_SUCCESS); | 303 | rb.Push(RESULT_SUCCESS); |
| 302 | rb.PushCopyObjects(launchable_event); | 304 | rb.PushCopyObjects(launchable_event.readable); |
| 303 | } | 305 | } |
| 304 | 306 | ||
| 305 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { | 307 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { |
| @@ -348,36 +350,38 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c | |||
| 348 | 350 | ||
| 349 | AppletMessageQueue::AppletMessageQueue() { | 351 | AppletMessageQueue::AppletMessageQueue() { |
| 350 | auto& kernel = Core::System::GetInstance().Kernel(); | 352 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 351 | on_new_message = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, | 353 | on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, |
| 352 | "AMMessageQueue:OnMessageRecieved"); | 354 | "AMMessageQueue:OnMessageRecieved"); |
| 353 | on_operation_mode_changed = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, | 355 | on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair( |
| 354 | "AMMessageQueue:OperationModeChanged"); | 356 | kernel, Kernel::ResetType::OneShot, "AMMessageQueue:OperationModeChanged"); |
| 355 | } | 357 | } |
| 356 | 358 | ||
| 357 | AppletMessageQueue::~AppletMessageQueue() = default; | 359 | AppletMessageQueue::~AppletMessageQueue() = default; |
| 358 | 360 | ||
| 359 | const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetMesssageRecieveEvent() const { | 361 | const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetMesssageRecieveEvent() |
| 360 | return on_new_message; | 362 | const { |
| 363 | return on_new_message.readable; | ||
| 361 | } | 364 | } |
| 362 | 365 | ||
| 363 | const Kernel::SharedPtr<Kernel::Event>& AppletMessageQueue::GetOperationModeChangedEvent() const { | 366 | const Kernel::SharedPtr<Kernel::ReadableEvent>& AppletMessageQueue::GetOperationModeChangedEvent() |
| 364 | return on_operation_mode_changed; | 367 | const { |
| 368 | return on_operation_mode_changed.readable; | ||
| 365 | } | 369 | } |
| 366 | 370 | ||
| 367 | void AppletMessageQueue::PushMessage(AppletMessage msg) { | 371 | void AppletMessageQueue::PushMessage(AppletMessage msg) { |
| 368 | messages.push(msg); | 372 | messages.push(msg); |
| 369 | on_new_message->Signal(); | 373 | on_new_message.writable->Signal(); |
| 370 | } | 374 | } |
| 371 | 375 | ||
| 372 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { | 376 | AppletMessageQueue::AppletMessage AppletMessageQueue::PopMessage() { |
| 373 | if (messages.empty()) { | 377 | if (messages.empty()) { |
| 374 | on_new_message->Clear(); | 378 | on_new_message.writable->Clear(); |
| 375 | return AppletMessage::NoMessage; | 379 | return AppletMessage::NoMessage; |
| 376 | } | 380 | } |
| 377 | auto msg = messages.front(); | 381 | auto msg = messages.front(); |
| 378 | messages.pop(); | 382 | messages.pop(); |
| 379 | if (messages.empty()) { | 383 | if (messages.empty()) { |
| 380 | on_new_message->Clear(); | 384 | on_new_message.writable->Clear(); |
| 381 | } | 385 | } |
| 382 | return msg; | 386 | return msg; |
| 383 | } | 387 | } |
| @@ -389,7 +393,7 @@ std::size_t AppletMessageQueue::GetMessageCount() const { | |||
| 389 | void AppletMessageQueue::OperationModeChanged() { | 393 | void AppletMessageQueue::OperationModeChanged() { |
| 390 | PushMessage(AppletMessage::OperationModeChanged); | 394 | PushMessage(AppletMessage::OperationModeChanged); |
| 391 | PushMessage(AppletMessage::PerformanceModeChanged); | 395 | PushMessage(AppletMessage::PerformanceModeChanged); |
| 392 | on_operation_mode_changed->Signal(); | 396 | on_operation_mode_changed.writable->Signal(); |
| 393 | } | 397 | } |
| 394 | 398 | ||
| 395 | ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue) | 399 | ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_queue) |
| @@ -426,9 +430,6 @@ ICommonStateGetter::ICommonStateGetter(std::shared_ptr<AppletMessageQueue> msg_q | |||
| 426 | // clang-format on | 430 | // clang-format on |
| 427 | 431 | ||
| 428 | RegisterHandlers(functions); | 432 | RegisterHandlers(functions); |
| 429 | |||
| 430 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 431 | event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ICommonStateGetter:Event"); | ||
| 432 | } | 433 | } |
| 433 | 434 | ||
| 434 | ICommonStateGetter::~ICommonStateGetter() = default; | 435 | ICommonStateGetter::~ICommonStateGetter() = default; |
| @@ -564,8 +565,8 @@ private: | |||
| 564 | void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { | 565 | void GetAppletStateChangedEvent(Kernel::HLERequestContext& ctx) { |
| 565 | LOG_DEBUG(Service_AM, "called"); | 566 | LOG_DEBUG(Service_AM, "called"); |
| 566 | 567 | ||
| 568 | applet->GetBroker().SignalStateChanged(); | ||
| 567 | const auto event = applet->GetBroker().GetStateChangedEvent(); | 569 | const auto event = applet->GetBroker().GetStateChangedEvent(); |
| 568 | event->Signal(); | ||
| 569 | 570 | ||
| 570 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 571 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 571 | rb.Push(RESULT_SUCCESS); | 572 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 44c1bcde5..34c45fadf 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -6,12 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <queue> | 8 | #include <queue> |
| 9 | #include "core/hle/kernel/writable_event.h" | ||
| 9 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 10 | 11 | ||
| 11 | namespace Kernel { | ||
| 12 | class Event; | ||
| 13 | } | ||
| 14 | |||
| 15 | namespace Service { | 12 | namespace Service { |
| 16 | namespace NVFlinger { | 13 | namespace NVFlinger { |
| 17 | class NVFlinger; | 14 | class NVFlinger; |
| @@ -52,8 +49,8 @@ public: | |||
| 52 | AppletMessageQueue(); | 49 | AppletMessageQueue(); |
| 53 | ~AppletMessageQueue(); | 50 | ~AppletMessageQueue(); |
| 54 | 51 | ||
| 55 | const Kernel::SharedPtr<Kernel::Event>& GetMesssageRecieveEvent() const; | 52 | const Kernel::SharedPtr<Kernel::ReadableEvent>& GetMesssageRecieveEvent() const; |
| 56 | const Kernel::SharedPtr<Kernel::Event>& GetOperationModeChangedEvent() const; | 53 | const Kernel::SharedPtr<Kernel::ReadableEvent>& GetOperationModeChangedEvent() const; |
| 57 | void PushMessage(AppletMessage msg); | 54 | void PushMessage(AppletMessage msg); |
| 58 | AppletMessage PopMessage(); | 55 | AppletMessage PopMessage(); |
| 59 | std::size_t GetMessageCount() const; | 56 | std::size_t GetMessageCount() const; |
| @@ -61,8 +58,8 @@ public: | |||
| 61 | 58 | ||
| 62 | private: | 59 | private: |
| 63 | std::queue<AppletMessage> messages; | 60 | std::queue<AppletMessage> messages; |
| 64 | Kernel::SharedPtr<Kernel::Event> on_new_message; | 61 | Kernel::EventPair on_new_message; |
| 65 | Kernel::SharedPtr<Kernel::Event> on_operation_mode_changed; | 62 | Kernel::EventPair on_operation_mode_changed; |
| 66 | }; | 63 | }; |
| 67 | 64 | ||
| 68 | class IWindowController final : public ServiceFramework<IWindowController> { | 65 | class IWindowController final : public ServiceFramework<IWindowController> { |
| @@ -122,7 +119,7 @@ private: | |||
| 122 | void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); | 119 | void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); |
| 123 | 120 | ||
| 124 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; | 121 | std::shared_ptr<NVFlinger::NVFlinger> nvflinger; |
| 125 | Kernel::SharedPtr<Kernel::Event> launchable_event; | 122 | Kernel::EventPair launchable_event; |
| 126 | u32 idle_time_detection_extension = 0; | 123 | u32 idle_time_detection_extension = 0; |
| 127 | }; | 124 | }; |
| 128 | 125 | ||
| @@ -151,7 +148,6 @@ private: | |||
| 151 | void GetBootMode(Kernel::HLERequestContext& ctx); | 148 | void GetBootMode(Kernel::HLERequestContext& ctx); |
| 152 | void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); | 149 | void GetDefaultDisplayResolution(Kernel::HLERequestContext& ctx); |
| 153 | 150 | ||
| 154 | Kernel::SharedPtr<Kernel::Event> event; | ||
| 155 | std::shared_ptr<AppletMessageQueue> msg_queue; | 151 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 156 | }; | 152 | }; |
| 157 | 153 | ||
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index becbadd06..47da35537 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -5,8 +5,9 @@ | |||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include "common/assert.h" | 6 | #include "common/assert.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hle/kernel/event.h" | 8 | #include "core/hle/kernel/readable_event.h" |
| 9 | #include "core/hle/kernel/server_port.h" | 9 | #include "core/hle/kernel/server_port.h" |
| 10 | #include "core/hle/kernel/writable_event.h" | ||
| 10 | #include "core/hle/service/am/am.h" | 11 | #include "core/hle/service/am/am.h" |
| 11 | #include "core/hle/service/am/applets/applets.h" | 12 | #include "core/hle/service/am/applets/applets.h" |
| 12 | 13 | ||
| @@ -14,11 +15,11 @@ namespace Service::AM::Applets { | |||
| 14 | 15 | ||
| 15 | AppletDataBroker::AppletDataBroker() { | 16 | AppletDataBroker::AppletDataBroker() { |
| 16 | auto& kernel = Core::System::GetInstance().Kernel(); | 17 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 17 | state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, | 18 | state_changed_event = Kernel::WritableEvent::CreateEventPair( |
| 18 | "ILibraryAppletAccessor:StateChangedEvent"); | 19 | kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:StateChangedEvent"); |
| 19 | pop_out_data_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, | 20 | pop_out_data_event = Kernel::WritableEvent::CreateEventPair( |
| 20 | "ILibraryAppletAccessor:PopDataOutEvent"); | 21 | kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopDataOutEvent"); |
| 21 | pop_interactive_out_data_event = Kernel::Event::Create( | 22 | pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair( |
| 22 | kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); | 23 | kernel, Kernel::ResetType::OneShot, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); |
| 23 | } | 24 | } |
| 24 | 25 | ||
| @@ -66,7 +67,7 @@ void AppletDataBroker::PushNormalDataFromGame(IStorage storage) { | |||
| 66 | 67 | ||
| 67 | void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) { | 68 | void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) { |
| 68 | out_channel.push(std::make_unique<IStorage>(storage)); | 69 | out_channel.push(std::make_unique<IStorage>(storage)); |
| 69 | pop_out_data_event->Signal(); | 70 | pop_out_data_event.writable->Signal(); |
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) { | 73 | void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) { |
| @@ -75,23 +76,23 @@ void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) { | |||
| 75 | 76 | ||
| 76 | void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) { | 77 | void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) { |
| 77 | out_interactive_channel.push(std::make_unique<IStorage>(storage)); | 78 | out_interactive_channel.push(std::make_unique<IStorage>(storage)); |
| 78 | pop_interactive_out_data_event->Signal(); | 79 | pop_interactive_out_data_event.writable->Signal(); |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | void AppletDataBroker::SignalStateChanged() const { | 82 | void AppletDataBroker::SignalStateChanged() const { |
| 82 | state_changed_event->Signal(); | 83 | state_changed_event.writable->Signal(); |
| 83 | } | 84 | } |
| 84 | 85 | ||
| 85 | Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetNormalDataEvent() const { | 86 | Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetNormalDataEvent() const { |
| 86 | return pop_out_data_event; | 87 | return pop_out_data_event.readable; |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetInteractiveDataEvent() const { | 90 | Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetInteractiveDataEvent() const { |
| 90 | return pop_interactive_out_data_event; | 91 | return pop_interactive_out_data_event.readable; |
| 91 | } | 92 | } |
| 92 | 93 | ||
| 93 | Kernel::SharedPtr<Kernel::Event> AppletDataBroker::GetStateChangedEvent() const { | 94 | Kernel::SharedPtr<Kernel::ReadableEvent> AppletDataBroker::GetStateChangedEvent() const { |
| 94 | return state_changed_event; | 95 | return state_changed_event.readable; |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | Applet::Applet() = default; | 98 | Applet::Applet() = default; |
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index f65ea119c..b0a8913c3 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h | |||
| @@ -8,13 +8,10 @@ | |||
| 8 | #include <queue> | 8 | #include <queue> |
| 9 | #include "common/swap.h" | 9 | #include "common/swap.h" |
| 10 | #include "core/hle/kernel/kernel.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/writable_event.h" | ||
| 11 | 12 | ||
| 12 | union ResultCode; | 13 | union ResultCode; |
| 13 | 14 | ||
| 14 | namespace Kernel { | ||
| 15 | class Event; | ||
| 16 | } | ||
| 17 | |||
| 18 | namespace Service::AM { | 15 | namespace Service::AM { |
| 19 | 16 | ||
| 20 | class IStorage; | 17 | class IStorage; |
| @@ -40,9 +37,9 @@ public: | |||
| 40 | 37 | ||
| 41 | void SignalStateChanged() const; | 38 | void SignalStateChanged() const; |
| 42 | 39 | ||
| 43 | Kernel::SharedPtr<Kernel::Event> GetNormalDataEvent() const; | 40 | Kernel::SharedPtr<Kernel::ReadableEvent> GetNormalDataEvent() const; |
| 44 | Kernel::SharedPtr<Kernel::Event> GetInteractiveDataEvent() const; | 41 | Kernel::SharedPtr<Kernel::ReadableEvent> GetInteractiveDataEvent() const; |
| 45 | Kernel::SharedPtr<Kernel::Event> GetStateChangedEvent() const; | 42 | Kernel::SharedPtr<Kernel::ReadableEvent> GetStateChangedEvent() const; |
| 46 | 43 | ||
| 47 | private: | 44 | private: |
| 48 | // Queues are named from applet's perspective | 45 | // Queues are named from applet's perspective |
| @@ -59,13 +56,13 @@ private: | |||
| 59 | // PopInteractiveDataToGame and PushInteractiveDataFromApplet | 56 | // PopInteractiveDataToGame and PushInteractiveDataFromApplet |
| 60 | std::queue<std::unique_ptr<IStorage>> out_interactive_channel; | 57 | std::queue<std::unique_ptr<IStorage>> out_interactive_channel; |
| 61 | 58 | ||
| 62 | Kernel::SharedPtr<Kernel::Event> state_changed_event; | 59 | Kernel::EventPair state_changed_event; |
| 63 | 60 | ||
| 64 | // Signaled on PushNormalDataFromApplet | 61 | // Signaled on PushNormalDataFromApplet |
| 65 | Kernel::SharedPtr<Kernel::Event> pop_out_data_event; | 62 | Kernel::EventPair pop_out_data_event; |
| 66 | 63 | ||
| 67 | // Signaled on PushInteractiveDataFromApplet | 64 | // Signaled on PushInteractiveDataFromApplet |
| 68 | Kernel::SharedPtr<Kernel::Event> pop_interactive_out_data_event; | 65 | Kernel::EventPair pop_interactive_out_data_event; |
| 69 | }; | 66 | }; |
| 70 | 67 | ||
| 71 | class Applet { | 68 | class Applet { |
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index bacf19de2..0417fdb92 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -13,8 +13,10 @@ | |||
| 13 | #include "core/file_sys/patch_manager.h" | 13 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/file_sys/registered_cache.h" | 14 | #include "core/file_sys/registered_cache.h" |
| 15 | #include "core/hle/ipc_helpers.h" | 15 | #include "core/hle/ipc_helpers.h" |
| 16 | #include "core/hle/kernel/event.h" | 16 | #include "core/hle/kernel/kernel.h" |
| 17 | #include "core/hle/kernel/process.h" | 17 | #include "core/hle/kernel/process.h" |
| 18 | #include "core/hle/kernel/readable_event.h" | ||
| 19 | #include "core/hle/kernel/writable_event.h" | ||
| 18 | #include "core/hle/service/aoc/aoc_u.h" | 20 | #include "core/hle/service/aoc/aoc_u.h" |
| 19 | #include "core/hle/service/filesystem/filesystem.h" | 21 | #include "core/hle/service/filesystem/filesystem.h" |
| 20 | #include "core/loader/loader.h" | 22 | #include "core/loader/loader.h" |
| @@ -32,14 +34,14 @@ static std::vector<u64> AccumulateAOCTitleIDs() { | |||
| 32 | std::vector<u64> add_on_content; | 34 | std::vector<u64> add_on_content; |
| 33 | const auto rcu = FileSystem::GetUnionContents(); | 35 | const auto rcu = FileSystem::GetUnionContents(); |
| 34 | const auto list = | 36 | const auto list = |
| 35 | rcu->ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); | 37 | rcu.ListEntriesFilter(FileSys::TitleType::AOC, FileSys::ContentRecordType::Data); |
| 36 | std::transform(list.begin(), list.end(), std::back_inserter(add_on_content), | 38 | std::transform(list.begin(), list.end(), std::back_inserter(add_on_content), |
| 37 | [](const FileSys::RegisteredCacheEntry& rce) { return rce.title_id; }); | 39 | [](const FileSys::RegisteredCacheEntry& rce) { return rce.title_id; }); |
| 38 | add_on_content.erase( | 40 | add_on_content.erase( |
| 39 | std::remove_if( | 41 | std::remove_if( |
| 40 | add_on_content.begin(), add_on_content.end(), | 42 | add_on_content.begin(), add_on_content.end(), |
| 41 | [&rcu](u64 tid) { | 43 | [&rcu](u64 tid) { |
| 42 | return rcu->GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() != | 44 | return rcu.GetEntry(tid, FileSys::ContentRecordType::Data)->GetStatus() != |
| 43 | Loader::ResultStatus::Success; | 45 | Loader::ResultStatus::Success; |
| 44 | }), | 46 | }), |
| 45 | add_on_content.end()); | 47 | add_on_content.end()); |
| @@ -61,8 +63,8 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs | |||
| 61 | RegisterHandlers(functions); | 63 | RegisterHandlers(functions); |
| 62 | 64 | ||
| 63 | auto& kernel = Core::System::GetInstance().Kernel(); | 65 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 64 | aoc_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, | 66 | aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, |
| 65 | "GetAddOnContentListChanged:Event"); | 67 | "GetAddOnContentListChanged:Event"); |
| 66 | } | 68 | } |
| 67 | 69 | ||
| 68 | AOC_U::~AOC_U() = default; | 70 | AOC_U::~AOC_U() = default; |
| @@ -144,7 +146,7 @@ void AOC_U::GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx) { | |||
| 144 | 146 | ||
| 145 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 147 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 146 | rb.Push(RESULT_SUCCESS); | 148 | rb.Push(RESULT_SUCCESS); |
| 147 | rb.PushCopyObjects(aoc_change_event); | 149 | rb.PushCopyObjects(aoc_change_event.readable); |
| 148 | } | 150 | } |
| 149 | 151 | ||
| 150 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 152 | void InstallInterfaces(SM::ServiceManager& service_manager) { |
diff --git a/src/core/hle/service/aoc/aoc_u.h b/src/core/hle/service/aoc/aoc_u.h index 68d94fdaa..5effea730 100644 --- a/src/core/hle/service/aoc/aoc_u.h +++ b/src/core/hle/service/aoc/aoc_u.h | |||
| @@ -6,6 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | #include "core/hle/service/service.h" | 7 | #include "core/hle/service/service.h" |
| 8 | 8 | ||
| 9 | namespace Kernel { | ||
| 10 | class WritableEvent; | ||
| 11 | } | ||
| 12 | |||
| 9 | namespace Service::AOC { | 13 | namespace Service::AOC { |
| 10 | 14 | ||
| 11 | class AOC_U final : public ServiceFramework<AOC_U> { | 15 | class AOC_U final : public ServiceFramework<AOC_U> { |
| @@ -21,7 +25,7 @@ private: | |||
| 21 | void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx); | 25 | void GetAddOnContentListChangedEvent(Kernel::HLERequestContext& ctx); |
| 22 | 26 | ||
| 23 | std::vector<u64> add_on_content; | 27 | std::vector<u64> add_on_content; |
| 24 | Kernel::SharedPtr<Kernel::Event> aoc_change_event; | 28 | Kernel::EventPair aoc_change_event; |
| 25 | }; | 29 | }; |
| 26 | 30 | ||
| 27 | /// Registers all AOC services with the specified service manager. | 31 | /// Registers all AOC services with the specified service manager. |
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 2ee9bc273..dc6a6b188 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp | |||
| @@ -13,8 +13,10 @@ | |||
| 13 | #include "common/swap.h" | 13 | #include "common/swap.h" |
| 14 | #include "core/core.h" | 14 | #include "core/core.h" |
| 15 | #include "core/hle/ipc_helpers.h" | 15 | #include "core/hle/ipc_helpers.h" |
| 16 | #include "core/hle/kernel/event.h" | ||
| 17 | #include "core/hle/kernel/hle_ipc.h" | 16 | #include "core/hle/kernel/hle_ipc.h" |
| 17 | #include "core/hle/kernel/kernel.h" | ||
| 18 | #include "core/hle/kernel/readable_event.h" | ||
| 19 | #include "core/hle/kernel/writable_event.h" | ||
| 18 | #include "core/hle/service/audio/audout_u.h" | 20 | #include "core/hle/service/audio/audout_u.h" |
| 19 | #include "core/memory.h" | 21 | #include "core/memory.h" |
| 20 | 22 | ||
| @@ -46,8 +48,8 @@ class IAudioOut final : public ServiceFramework<IAudioOut> { | |||
| 46 | public: | 48 | public: |
| 47 | IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core, std::string&& device_name, | 49 | IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core, std::string&& device_name, |
| 48 | std::string&& unique_name) | 50 | std::string&& unique_name) |
| 49 | : ServiceFramework("IAudioOut"), audio_core(audio_core), audio_params(audio_params), | 51 | : ServiceFramework("IAudioOut"), audio_core(audio_core), |
| 50 | device_name(std::move(device_name)) { | 52 | device_name(std::move(device_name)), audio_params(audio_params) { |
| 51 | 53 | ||
| 52 | static const FunctionInfo functions[] = { | 54 | static const FunctionInfo functions[] = { |
| 53 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, | 55 | {0, &IAudioOut::GetAudioOutState, "GetAudioOutState"}, |
| @@ -67,11 +69,12 @@ public: | |||
| 67 | 69 | ||
| 68 | // This is the event handle used to check if the audio buffer was released | 70 | // This is the event handle used to check if the audio buffer was released |
| 69 | auto& kernel = Core::System::GetInstance().Kernel(); | 71 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 70 | buffer_event = | 72 | buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, |
| 71 | Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioOutBufferReleased"); | 73 | "IAudioOutBufferReleased"); |
| 72 | 74 | ||
| 73 | stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count, | 75 | stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count, |
| 74 | std::move(unique_name), [=]() { buffer_event->Signal(); }); | 76 | std::move(unique_name), |
| 77 | [=]() { buffer_event.writable->Signal(); }); | ||
| 75 | } | 78 | } |
| 76 | 79 | ||
| 77 | private: | 80 | private: |
| @@ -121,7 +124,7 @@ private: | |||
| 121 | 124 | ||
| 122 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 125 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 123 | rb.Push(RESULT_SUCCESS); | 126 | rb.Push(RESULT_SUCCESS); |
| 124 | rb.PushCopyObjects(buffer_event); | 127 | rb.PushCopyObjects(buffer_event.readable); |
| 125 | } | 128 | } |
| 126 | 129 | ||
| 127 | void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) { | 130 | void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) { |
| @@ -187,8 +190,8 @@ private: | |||
| 187 | 190 | ||
| 188 | AudoutParams audio_params{}; | 191 | AudoutParams audio_params{}; |
| 189 | 192 | ||
| 190 | /// This is the evend handle used to check if the audio buffer was released | 193 | /// This is the event handle used to check if the audio buffer was released |
| 191 | Kernel::SharedPtr<Kernel::Event> buffer_event; | 194 | Kernel::EventPair buffer_event; |
| 192 | }; | 195 | }; |
| 193 | 196 | ||
| 194 | void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) { | 197 | void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 1c418a9bb..945259c7d 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -12,8 +12,10 @@ | |||
| 12 | #include "common/logging/log.h" | 12 | #include "common/logging/log.h" |
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/hle/ipc_helpers.h" | 14 | #include "core/hle/ipc_helpers.h" |
| 15 | #include "core/hle/kernel/event.h" | ||
| 16 | #include "core/hle/kernel/hle_ipc.h" | 15 | #include "core/hle/kernel/hle_ipc.h" |
| 16 | #include "core/hle/kernel/kernel.h" | ||
| 17 | #include "core/hle/kernel/readable_event.h" | ||
| 18 | #include "core/hle/kernel/writable_event.h" | ||
| 17 | #include "core/hle/service/audio/audren_u.h" | 19 | #include "core/hle/service/audio/audren_u.h" |
| 18 | 20 | ||
| 19 | namespace Service::Audio { | 21 | namespace Service::Audio { |
| @@ -41,14 +43,14 @@ public: | |||
| 41 | RegisterHandlers(functions); | 43 | RegisterHandlers(functions); |
| 42 | 44 | ||
| 43 | auto& kernel = Core::System::GetInstance().Kernel(); | 45 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 44 | system_event = | 46 | system_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, |
| 45 | Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent"); | 47 | "IAudioRenderer:SystemEvent"); |
| 46 | renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event); | 48 | renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event.writable); |
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | private: | 51 | private: |
| 50 | void UpdateAudioCallback() { | 52 | void UpdateAudioCallback() { |
| 51 | system_event->Signal(); | 53 | system_event.writable->Signal(); |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 54 | void GetSampleRate(Kernel::HLERequestContext& ctx) { | 56 | void GetSampleRate(Kernel::HLERequestContext& ctx) { |
| @@ -112,7 +114,7 @@ private: | |||
| 112 | 114 | ||
| 113 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 115 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 114 | rb.Push(RESULT_SUCCESS); | 116 | rb.Push(RESULT_SUCCESS); |
| 115 | rb.PushCopyObjects(system_event); | 117 | rb.PushCopyObjects(system_event.readable); |
| 116 | } | 118 | } |
| 117 | 119 | ||
| 118 | void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { | 120 | void SetRenderingTimeLimit(Kernel::HLERequestContext& ctx) { |
| @@ -135,7 +137,7 @@ private: | |||
| 135 | rb.Push(rendering_time_limit_percent); | 137 | rb.Push(rendering_time_limit_percent); |
| 136 | } | 138 | } |
| 137 | 139 | ||
| 138 | Kernel::SharedPtr<Kernel::Event> system_event; | 140 | Kernel::EventPair system_event; |
| 139 | std::unique_ptr<AudioCore::AudioRenderer> renderer; | 141 | std::unique_ptr<AudioCore::AudioRenderer> renderer; |
| 140 | u32 rendering_time_limit_percent = 100; | 142 | u32 rendering_time_limit_percent = 100; |
| 141 | }; | 143 | }; |
| @@ -162,8 +164,8 @@ public: | |||
| 162 | RegisterHandlers(functions); | 164 | RegisterHandlers(functions); |
| 163 | 165 | ||
| 164 | auto& kernel = Core::System::GetInstance().Kernel(); | 166 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 165 | buffer_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, | 167 | buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, |
| 166 | "IAudioOutBufferReleasedEvent"); | 168 | "IAudioOutBufferReleasedEvent"); |
| 167 | } | 169 | } |
| 168 | 170 | ||
| 169 | private: | 171 | private: |
| @@ -207,11 +209,11 @@ private: | |||
| 207 | void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { | 209 | void QueryAudioDeviceSystemEvent(Kernel::HLERequestContext& ctx) { |
| 208 | LOG_WARNING(Service_Audio, "(STUBBED) called"); | 210 | LOG_WARNING(Service_Audio, "(STUBBED) called"); |
| 209 | 211 | ||
| 210 | buffer_event->Signal(); | 212 | buffer_event.writable->Signal(); |
| 211 | 213 | ||
| 212 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 214 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 213 | rb.Push(RESULT_SUCCESS); | 215 | rb.Push(RESULT_SUCCESS); |
| 214 | rb.PushCopyObjects(buffer_event); | 216 | rb.PushCopyObjects(buffer_event.readable); |
| 215 | } | 217 | } |
| 216 | 218 | ||
| 217 | void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { | 219 | void GetActiveChannelCount(Kernel::HLERequestContext& ctx) { |
| @@ -222,7 +224,7 @@ private: | |||
| 222 | rb.Push<u32>(1); | 224 | rb.Push<u32>(1); |
| 223 | } | 225 | } |
| 224 | 226 | ||
| 225 | Kernel::SharedPtr<Kernel::Event> buffer_event; | 227 | Kernel::EventPair buffer_event; |
| 226 | 228 | ||
| 227 | }; // namespace Audio | 229 | }; // namespace Audio |
| 228 | 230 | ||
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index 2eadcdd05..5704ca0ab 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp | |||
| @@ -4,8 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/event.h" | ||
| 8 | #include "core/hle/kernel/hle_ipc.h" | 7 | #include "core/hle/kernel/hle_ipc.h" |
| 8 | #include "core/hle/kernel/kernel.h" | ||
| 9 | #include "core/hle/kernel/readable_event.h" | ||
| 10 | #include "core/hle/kernel/writable_event.h" | ||
| 9 | #include "core/hle/service/btdrv/btdrv.h" | 11 | #include "core/hle/service/btdrv/btdrv.h" |
| 10 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 11 | #include "core/hle/service/sm/sm.h" | 13 | #include "core/hle/service/sm/sm.h" |
| @@ -30,20 +32,22 @@ public: | |||
| 30 | }; | 32 | }; |
| 31 | // clang-format on | 33 | // clang-format on |
| 32 | RegisterHandlers(functions); | 34 | RegisterHandlers(functions); |
| 35 | |||
| 36 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 37 | register_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, | ||
| 38 | "BT:RegisterEvent"); | ||
| 33 | } | 39 | } |
| 34 | 40 | ||
| 35 | private: | 41 | private: |
| 36 | void RegisterEvent(Kernel::HLERequestContext& ctx) { | 42 | void RegisterEvent(Kernel::HLERequestContext& ctx) { |
| 37 | LOG_WARNING(Service_BTM, "(STUBBED) called"); | 43 | LOG_WARNING(Service_BTM, "(STUBBED) called"); |
| 38 | 44 | ||
| 39 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 40 | register_event = | ||
| 41 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "BT:RegisterEvent"); | ||
| 42 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 45 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 43 | rb.Push(RESULT_SUCCESS); | 46 | rb.Push(RESULT_SUCCESS); |
| 44 | rb.PushCopyObjects(register_event); | 47 | rb.PushCopyObjects(register_event.readable); |
| 45 | } | 48 | } |
| 46 | Kernel::SharedPtr<Kernel::Event> register_event; | 49 | |
| 50 | Kernel::EventPair register_event; | ||
| 47 | }; | 51 | }; |
| 48 | 52 | ||
| 49 | class BtDrv final : public ServiceFramework<BtDrv> { | 53 | class BtDrv final : public ServiceFramework<BtDrv> { |
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 463a79351..ef7398a23 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp | |||
| @@ -6,8 +6,10 @@ | |||
| 6 | 6 | ||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/event.h" | ||
| 10 | #include "core/hle/kernel/hle_ipc.h" | 9 | #include "core/hle/kernel/hle_ipc.h" |
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | #include "core/hle/kernel/readable_event.h" | ||
| 12 | #include "core/hle/kernel/writable_event.h" | ||
| 11 | #include "core/hle/service/btm/btm.h" | 13 | #include "core/hle/service/btm/btm.h" |
| 12 | #include "core/hle/service/service.h" | 14 | #include "core/hle/service/service.h" |
| 13 | 15 | ||
| @@ -53,53 +55,55 @@ public: | |||
| 53 | }; | 55 | }; |
| 54 | // clang-format on | 56 | // clang-format on |
| 55 | RegisterHandlers(functions); | 57 | RegisterHandlers(functions); |
| 58 | |||
| 59 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 60 | scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, | ||
| 61 | "IBtmUserCore:ScanEvent"); | ||
| 62 | connection_event = Kernel::WritableEvent::CreateEventPair( | ||
| 63 | kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConnectionEvent"); | ||
| 64 | service_discovery = Kernel::WritableEvent::CreateEventPair( | ||
| 65 | kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery"); | ||
| 66 | config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, | ||
| 67 | "IBtmUserCore:ConfigEvent"); | ||
| 56 | } | 68 | } |
| 57 | 69 | ||
| 58 | private: | 70 | private: |
| 59 | void GetScanEvent(Kernel::HLERequestContext& ctx) { | 71 | void GetScanEvent(Kernel::HLERequestContext& ctx) { |
| 60 | LOG_WARNING(Service_BTM, "(STUBBED) called"); | 72 | LOG_WARNING(Service_BTM, "(STUBBED) called"); |
| 61 | 73 | ||
| 62 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 63 | scan_event = | ||
| 64 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ScanEvent"); | ||
| 65 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 74 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 66 | rb.Push(RESULT_SUCCESS); | 75 | rb.Push(RESULT_SUCCESS); |
| 67 | rb.PushCopyObjects(scan_event); | 76 | rb.PushCopyObjects(scan_event.readable); |
| 68 | } | 77 | } |
| 78 | |||
| 69 | void GetConnectionEvent(Kernel::HLERequestContext& ctx) { | 79 | void GetConnectionEvent(Kernel::HLERequestContext& ctx) { |
| 70 | LOG_WARNING(Service_BTM, "(STUBBED) called"); | 80 | LOG_WARNING(Service_BTM, "(STUBBED) called"); |
| 71 | 81 | ||
| 72 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 73 | connection_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, | ||
| 74 | "IBtmUserCore:ConnectionEvent"); | ||
| 75 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 82 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 76 | rb.Push(RESULT_SUCCESS); | 83 | rb.Push(RESULT_SUCCESS); |
| 77 | rb.PushCopyObjects(connection_event); | 84 | rb.PushCopyObjects(connection_event.readable); |
| 78 | } | 85 | } |
| 86 | |||
| 79 | void GetDiscoveryEvent(Kernel::HLERequestContext& ctx) { | 87 | void GetDiscoveryEvent(Kernel::HLERequestContext& ctx) { |
| 80 | LOG_WARNING(Service_BTM, "(STUBBED) called"); | 88 | LOG_WARNING(Service_BTM, "(STUBBED) called"); |
| 81 | 89 | ||
| 82 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 83 | service_discovery = | ||
| 84 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery"); | ||
| 85 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 90 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 86 | rb.Push(RESULT_SUCCESS); | 91 | rb.Push(RESULT_SUCCESS); |
| 87 | rb.PushCopyObjects(service_discovery); | 92 | rb.PushCopyObjects(service_discovery.readable); |
| 88 | } | 93 | } |
| 94 | |||
| 89 | void GetConfigEvent(Kernel::HLERequestContext& ctx) { | 95 | void GetConfigEvent(Kernel::HLERequestContext& ctx) { |
| 90 | LOG_WARNING(Service_BTM, "(STUBBED) called"); | 96 | LOG_WARNING(Service_BTM, "(STUBBED) called"); |
| 91 | 97 | ||
| 92 | auto& kernel = Core::System::GetInstance().Kernel(); | ||
| 93 | config_event = | ||
| 94 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConfigEvent"); | ||
| 95 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 98 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 96 | rb.Push(RESULT_SUCCESS); | 99 | rb.Push(RESULT_SUCCESS); |
| 97 | rb.PushCopyObjects(config_event); | 100 | rb.PushCopyObjects(config_event.readable); |
| 98 | } | 101 | } |
| 99 | Kernel::SharedPtr<Kernel::Event> scan_event; | 102 | |
| 100 | Kernel::SharedPtr<Kernel::Event> connection_event; | 103 | Kernel::EventPair scan_event; |
| 101 | Kernel::SharedPtr<Kernel::Event> service_discovery; | 104 | Kernel::EventPair connection_event; |
| 102 | Kernel::SharedPtr<Kernel::Event> config_event; | 105 | Kernel::EventPair service_discovery; |
| 106 | Kernel::EventPair config_event; | ||
| 103 | }; | 107 | }; |
| 104 | 108 | ||
| 105 | class BTM_USR final : public ServiceFramework<BTM_USR> { | 109 | class BTM_USR final : public ServiceFramework<BTM_USR> { |
diff --git a/src/core/hle/service/erpt/erpt.cpp b/src/core/hle/service/erpt/erpt.cpp index ee11cd78e..d9b32954e 100644 --- a/src/core/hle/service/erpt/erpt.cpp +++ b/src/core/hle/service/erpt/erpt.cpp | |||
| @@ -17,11 +17,13 @@ public: | |||
| 17 | static const FunctionInfo functions[] = { | 17 | static const FunctionInfo functions[] = { |
| 18 | {0, nullptr, "SubmitContext"}, | 18 | {0, nullptr, "SubmitContext"}, |
| 19 | {1, nullptr, "CreateReport"}, | 19 | {1, nullptr, "CreateReport"}, |
| 20 | {2, nullptr, "Unknown1"}, | 20 | {2, nullptr, "SetInitialLaunchSettingsCompletionTime"}, |
| 21 | {3, nullptr, "Unknown2"}, | 21 | {3, nullptr, "ClearInitialLaunchSettingsCompletionTime"}, |
| 22 | {4, nullptr, "Unknown3"}, | 22 | {4, nullptr, "UpdatePowerOnTime"}, |
| 23 | {5, nullptr, "Unknown4"}, | 23 | {5, nullptr, "UpdateAwakeTime"}, |
| 24 | {6, nullptr, "Unknown5"}, | 24 | {6, nullptr, "SubmitMultipleCategoryContext"}, |
| 25 | {7, nullptr, "UpdateApplicationLaunchTime"}, | ||
| 26 | {8, nullptr, "ClearApplicationLaunchTime"}, | ||
| 25 | }; | 27 | }; |
| 26 | // clang-format on | 28 | // clang-format on |
| 27 | 29 | ||
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 2aa77f68d..b1490e6fa 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp | |||
| @@ -113,6 +113,18 @@ ResultCode VfsDirectoryServiceWrapper::DeleteDirectoryRecursively(const std::str | |||
| 113 | return RESULT_SUCCESS; | 113 | return RESULT_SUCCESS; |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | ResultCode VfsDirectoryServiceWrapper::CleanDirectoryRecursively(const std::string& path) const { | ||
| 117 | const std::string sanitized_path(FileUtil::SanitizePath(path)); | ||
| 118 | auto dir = GetDirectoryRelativeWrapped(backing, FileUtil::GetParentPath(sanitized_path)); | ||
| 119 | |||
| 120 | if (!dir->CleanSubdirectoryRecursive(FileUtil::GetFilename(sanitized_path))) { | ||
| 121 | // TODO(DarkLordZach): Find a better error code for this | ||
| 122 | return ResultCode(-1); | ||
| 123 | } | ||
| 124 | |||
| 125 | return RESULT_SUCCESS; | ||
| 126 | } | ||
| 127 | |||
| 116 | ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, | 128 | ResultCode VfsDirectoryServiceWrapper::RenameFile(const std::string& src_path_, |
| 117 | const std::string& dest_path_) const { | 129 | const std::string& dest_path_) const { |
| 118 | std::string src_path(FileUtil::SanitizePath(src_path_)); | 130 | std::string src_path(FileUtil::SanitizePath(src_path_)); |
| @@ -329,20 +341,9 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() { | |||
| 329 | return sdmc_factory->Open(); | 341 | return sdmc_factory->Open(); |
| 330 | } | 342 | } |
| 331 | 343 | ||
| 332 | std::shared_ptr<FileSys::RegisteredCacheUnion> registered_cache_union; | 344 | FileSys::RegisteredCacheUnion GetUnionContents() { |
| 333 | 345 | return FileSys::RegisteredCacheUnion{ | |
| 334 | std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents() { | 346 | {GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}}; |
| 335 | if (registered_cache_union == nullptr) { | ||
| 336 | registered_cache_union = | ||
| 337 | std::make_shared<FileSys::RegisteredCacheUnion>(std::vector<FileSys::RegisteredCache*>{ | ||
| 338 | GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}); | ||
| 339 | } | ||
| 340 | |||
| 341 | return registered_cache_union; | ||
| 342 | } | ||
| 343 | |||
| 344 | void ClearUnionContents() { | ||
| 345 | registered_cache_union = nullptr; | ||
| 346 | } | 347 | } |
| 347 | 348 | ||
| 348 | FileSys::RegisteredCache* GetSystemNANDContents() { | 349 | FileSys::RegisteredCache* GetSystemNANDContents() { |
| @@ -395,7 +396,6 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) { | |||
| 395 | bis_factory = nullptr; | 396 | bis_factory = nullptr; |
| 396 | save_data_factory = nullptr; | 397 | save_data_factory = nullptr; |
| 397 | sdmc_factory = nullptr; | 398 | sdmc_factory = nullptr; |
| 398 | ClearUnionContents(); | ||
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), | 401 | auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), |
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h index 0a6cb6635..965414be0 100644 --- a/src/core/hle/service/filesystem/filesystem.h +++ b/src/core/hle/service/filesystem/filesystem.h | |||
| @@ -48,8 +48,7 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space, | |||
| 48 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space); | 48 | ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space); |
| 49 | ResultVal<FileSys::VirtualDir> OpenSDMC(); | 49 | ResultVal<FileSys::VirtualDir> OpenSDMC(); |
| 50 | 50 | ||
| 51 | std::shared_ptr<FileSys::RegisteredCacheUnion> GetUnionContents(); | 51 | FileSys::RegisteredCacheUnion GetUnionContents(); |
| 52 | void ClearUnionContents(); | ||
| 53 | 52 | ||
| 54 | FileSys::RegisteredCache* GetSystemNANDContents(); | 53 | FileSys::RegisteredCache* GetSystemNANDContents(); |
| 55 | FileSys::RegisteredCache* GetUserNANDContents(); | 54 | FileSys::RegisteredCache* GetUserNANDContents(); |
| @@ -114,6 +113,18 @@ public: | |||
| 114 | ResultCode DeleteDirectoryRecursively(const std::string& path) const; | 113 | ResultCode DeleteDirectoryRecursively(const std::string& path) const; |
| 115 | 114 | ||
| 116 | /** | 115 | /** |
| 116 | * Cleans the specified directory. This is similar to DeleteDirectoryRecursively, | ||
| 117 | * in that it deletes all the contents of the specified directory, however, this | ||
| 118 | * function does *not* delete the directory itself. It only deletes everything | ||
| 119 | * within it. | ||
| 120 | * | ||
| 121 | * @param path Path relative to the archive. | ||
| 122 | * | ||
| 123 | * @return Result of the operation. | ||
| 124 | */ | ||
| 125 | ResultCode CleanDirectoryRecursively(const std::string& path) const; | ||
| 126 | |||
| 127 | /** | ||
| 117 | * Rename a File specified by its path | 128 | * Rename a File specified by its path |
| 118 | * @param src_path Source path relative to the archive | 129 | * @param src_path Source path relative to the archive |
| 119 | * @param dest_path Destination path relative to the archive | 130 | * @param dest_path Destination path relative to the archive |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 99d9ebc39..694ec40ec 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -291,7 +291,7 @@ public: | |||
| 291 | {10, &IFileSystem::Commit, "Commit"}, | 291 | {10, &IFileSystem::Commit, "Commit"}, |
| 292 | {11, nullptr, "GetFreeSpaceSize"}, | 292 | {11, nullptr, "GetFreeSpaceSize"}, |
| 293 | {12, nullptr, "GetTotalSpaceSize"}, | 293 | {12, nullptr, "GetTotalSpaceSize"}, |
| 294 | {13, nullptr, "CleanDirectoryRecursively"}, | 294 | {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, |
| 295 | {14, nullptr, "GetFileTimeStampRaw"}, | 295 | {14, nullptr, "GetFileTimeStampRaw"}, |
| 296 | {15, nullptr, "QueryEntry"}, | 296 | {15, nullptr, "QueryEntry"}, |
| 297 | }; | 297 | }; |
| @@ -361,6 +361,16 @@ public: | |||
| 361 | rb.Push(backend.DeleteDirectoryRecursively(name)); | 361 | rb.Push(backend.DeleteDirectoryRecursively(name)); |
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | void CleanDirectoryRecursively(Kernel::HLERequestContext& ctx) { | ||
| 365 | const auto file_buffer = ctx.ReadBuffer(); | ||
| 366 | const std::string name = Common::StringFromBuffer(file_buffer); | ||
| 367 | |||
| 368 | LOG_DEBUG(Service_FS, "called. Directory: {}", name); | ||
| 369 | |||
| 370 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 371 | rb.Push(backend.CleanDirectoryRecursively(name)); | ||
| 372 | } | ||
| 373 | |||
| 364 | void RenameFile(Kernel::HLERequestContext& ctx) { | 374 | void RenameFile(Kernel::HLERequestContext& ctx) { |
| 365 | IPC::RequestParser rp{ctx}; | 375 | IPC::RequestParser rp{ctx}; |
| 366 | 376 | ||
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 22e87a50a..d6829d0b8 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -12,7 +12,9 @@ | |||
| 12 | #include "core/core.h" | 12 | #include "core/core.h" |
| 13 | #include "core/core_timing.h" | 13 | #include "core/core_timing.h" |
| 14 | #include "core/frontend/input.h" | 14 | #include "core/frontend/input.h" |
| 15 | #include "core/hle/kernel/event.h" | 15 | #include "core/hle/kernel/kernel.h" |
| 16 | #include "core/hle/kernel/readable_event.h" | ||
| 17 | #include "core/hle/kernel/writable_event.h" | ||
| 16 | #include "core/hle/service/hid/controllers/npad.h" | 18 | #include "core/hle/service/hid/controllers/npad.h" |
| 17 | #include "core/settings.h" | 19 | #include "core/settings.h" |
| 18 | 20 | ||
| @@ -167,8 +169,8 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { | |||
| 167 | 169 | ||
| 168 | void Controller_NPad::OnInit() { | 170 | void Controller_NPad::OnInit() { |
| 169 | auto& kernel = Core::System::GetInstance().Kernel(); | 171 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 170 | styleset_changed_event = | 172 | styleset_changed_event = Kernel::WritableEvent::CreateEventPair( |
| 171 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged"); | 173 | kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged"); |
| 172 | 174 | ||
| 173 | if (!IsControllerActivated()) { | 175 | if (!IsControllerActivated()) { |
| 174 | return; | 176 | return; |
| @@ -494,7 +496,7 @@ void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) { | |||
| 494 | had_controller_update = true; | 496 | had_controller_update = true; |
| 495 | } | 497 | } |
| 496 | if (had_controller_update) { | 498 | if (had_controller_update) { |
| 497 | styleset_changed_event->Signal(); | 499 | styleset_changed_event.writable->Signal(); |
| 498 | } | 500 | } |
| 499 | } | 501 | } |
| 500 | } | 502 | } |
| @@ -509,7 +511,7 @@ std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const { | |||
| 509 | } | 511 | } |
| 510 | 512 | ||
| 511 | void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { | 513 | void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) { |
| 512 | styleset_changed_event->Signal(); | 514 | styleset_changed_event.writable->Signal(); |
| 513 | hold_type = joy_hold_type; | 515 | hold_type = joy_hold_type; |
| 514 | } | 516 | } |
| 515 | 517 | ||
| @@ -518,8 +520,9 @@ Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const { | |||
| 518 | } | 520 | } |
| 519 | 521 | ||
| 520 | void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { | 522 | void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) { |
| 521 | ASSERT(npad_id < shared_memory_entries.size()); | 523 | const std::size_t npad_index = NPadIdToIndex(npad_id); |
| 522 | shared_memory_entries[npad_id].pad_assignment = assignment_mode; | 524 | ASSERT(npad_index < shared_memory_entries.size()); |
| 525 | shared_memory_entries[npad_index].pad_assignment = assignment_mode; | ||
| 523 | } | 526 | } |
| 524 | 527 | ||
| 525 | void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | 528 | void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, |
| @@ -538,11 +541,11 @@ void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids, | |||
| 538 | last_processed_vibration = vibrations.back(); | 541 | last_processed_vibration = vibrations.back(); |
| 539 | } | 542 | } |
| 540 | 543 | ||
| 541 | Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const { | 544 | Kernel::SharedPtr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent() const { |
| 542 | // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should | 545 | // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should |
| 543 | // be signalled at least once, and signaled after a new controller is connected? | 546 | // be signalled at least once, and signaled after a new controller is connected? |
| 544 | styleset_changed_event->Signal(); | 547 | styleset_changed_event.writable->Signal(); |
| 545 | return styleset_changed_event; | 548 | return styleset_changed_event.readable; |
| 546 | } | 549 | } |
| 547 | 550 | ||
| 548 | Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { | 551 | Controller_NPad::Vibration Controller_NPad::GetLastVibration() const { |
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index abff6544d..29851f16a 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h | |||
| @@ -8,7 +8,8 @@ | |||
| 8 | #include "common/bit_field.h" | 8 | #include "common/bit_field.h" |
| 9 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 10 | #include "core/frontend/input.h" | 10 | #include "core/frontend/input.h" |
| 11 | #include "core/hle/kernel/event.h" | 11 | #include "core/hle/kernel/object.h" |
| 12 | #include "core/hle/kernel/writable_event.h" | ||
| 12 | #include "core/hle/service/hid/controllers/controller_base.h" | 13 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 13 | #include "core/settings.h" | 14 | #include "core/settings.h" |
| 14 | 15 | ||
| @@ -108,7 +109,7 @@ public: | |||
| 108 | void VibrateController(const std::vector<u32>& controller_ids, | 109 | void VibrateController(const std::vector<u32>& controller_ids, |
| 109 | const std::vector<Vibration>& vibrations); | 110 | const std::vector<Vibration>& vibrations); |
| 110 | 111 | ||
| 111 | Kernel::SharedPtr<Kernel::Event> GetStyleSetChangedEvent() const; | 112 | Kernel::SharedPtr<Kernel::ReadableEvent> GetStyleSetChangedEvent() const; |
| 112 | Vibration GetLastVibration() const; | 113 | Vibration GetLastVibration() const; |
| 113 | 114 | ||
| 114 | void AddNewController(NPadControllerType controller); | 115 | void AddNewController(NPadControllerType controller); |
| @@ -303,7 +304,7 @@ private: | |||
| 303 | sticks; | 304 | sticks; |
| 304 | std::vector<u32> supported_npad_id_types{}; | 305 | std::vector<u32> supported_npad_id_types{}; |
| 305 | NpadHoldType hold_type{NpadHoldType::Vertical}; | 306 | NpadHoldType hold_type{NpadHoldType::Vertical}; |
| 306 | Kernel::SharedPtr<Kernel::Event> styleset_changed_event; | 307 | Kernel::EventPair styleset_changed_event; |
| 307 | Vibration last_processed_vibration{}; | 308 | Vibration last_processed_vibration{}; |
| 308 | std::array<ControllerHolder, 10> connected_controllers{}; | 309 | std::array<ControllerHolder, 10> connected_controllers{}; |
| 309 | bool can_controllers_vibrate{true}; | 310 | bool can_controllers_vibrate{true}; |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 46496e9bb..2ec38c726 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -13,8 +13,9 @@ | |||
| 13 | #include "core/hle/ipc_helpers.h" | 13 | #include "core/hle/ipc_helpers.h" |
| 14 | #include "core/hle/kernel/client_port.h" | 14 | #include "core/hle/kernel/client_port.h" |
| 15 | #include "core/hle/kernel/client_session.h" | 15 | #include "core/hle/kernel/client_session.h" |
| 16 | #include "core/hle/kernel/event.h" | 16 | #include "core/hle/kernel/readable_event.h" |
| 17 | #include "core/hle/kernel/shared_memory.h" | 17 | #include "core/hle/kernel/shared_memory.h" |
| 18 | #include "core/hle/kernel/writable_event.h" | ||
| 18 | #include "core/hle/service/hid/hid.h" | 19 | #include "core/hle/service/hid/hid.h" |
| 19 | #include "core/hle/service/hid/irs.h" | 20 | #include "core/hle/service/hid/irs.h" |
| 20 | #include "core/hle/service/hid/xcd.h" | 21 | #include "core/hle/service/hid/xcd.h" |
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index ff9170c24..d5df112a0 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp | |||
| @@ -7,7 +7,9 @@ | |||
| 7 | #include "common/logging/log.h" | 7 | #include "common/logging/log.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/hle/ipc_helpers.h" | 9 | #include "core/hle/ipc_helpers.h" |
| 10 | #include "core/hle/kernel/event.h" | 10 | #include "core/hle/kernel/kernel.h" |
| 11 | #include "core/hle/kernel/readable_event.h" | ||
| 12 | #include "core/hle/kernel/writable_event.h" | ||
| 11 | #include "core/hle/lock.h" | 13 | #include "core/hle/lock.h" |
| 12 | #include "core/hle/service/hid/hid.h" | 14 | #include "core/hle/service/hid/hid.h" |
| 13 | #include "core/hle/service/nfp/nfp.h" | 15 | #include "core/hle/service/nfp/nfp.h" |
| @@ -23,8 +25,8 @@ constexpr ResultCode ERR_TAG_FAILED(ErrorModule::NFP, | |||
| 23 | Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) | 25 | Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) |
| 24 | : ServiceFramework(name), module(std::move(module)) { | 26 | : ServiceFramework(name), module(std::move(module)) { |
| 25 | auto& kernel = Core::System::GetInstance().Kernel(); | 27 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 26 | nfc_tag_load = | 28 | nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, |
| 27 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:NFCTagDetected"); | 29 | "IUser:NFCTagDetected"); |
| 28 | } | 30 | } |
| 29 | 31 | ||
| 30 | Module::Interface::~Interface() = default; | 32 | Module::Interface::~Interface() = default; |
| @@ -63,10 +65,10 @@ public: | |||
| 63 | RegisterHandlers(functions); | 65 | RegisterHandlers(functions); |
| 64 | 66 | ||
| 65 | auto& kernel = Core::System::GetInstance().Kernel(); | 67 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 66 | deactivate_event = | 68 | deactivate_event = Kernel::WritableEvent::CreateEventPair( |
| 67 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); | 69 | kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); |
| 68 | availability_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, | 70 | availability_change_event = Kernel::WritableEvent::CreateEventPair( |
| 69 | "IUser:AvailabilityChangeEvent"); | 71 | kernel, Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent"); |
| 70 | } | 72 | } |
| 71 | 73 | ||
| 72 | private: | 74 | private: |
| @@ -164,7 +166,7 @@ private: | |||
| 164 | 166 | ||
| 165 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 167 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 166 | rb.Push(RESULT_SUCCESS); | 168 | rb.Push(RESULT_SUCCESS); |
| 167 | rb.PushCopyObjects(deactivate_event); | 169 | rb.PushCopyObjects(deactivate_event.readable); |
| 168 | } | 170 | } |
| 169 | 171 | ||
| 170 | void StopDetection(Kernel::HLERequestContext& ctx) { | 172 | void StopDetection(Kernel::HLERequestContext& ctx) { |
| @@ -173,7 +175,7 @@ private: | |||
| 173 | switch (device_state) { | 175 | switch (device_state) { |
| 174 | case DeviceState::TagFound: | 176 | case DeviceState::TagFound: |
| 175 | case DeviceState::TagNearby: | 177 | case DeviceState::TagNearby: |
| 176 | deactivate_event->Signal(); | 178 | deactivate_event.writable->Signal(); |
| 177 | device_state = DeviceState::Initialized; | 179 | device_state = DeviceState::Initialized; |
| 178 | break; | 180 | break; |
| 179 | case DeviceState::SearchingForTag: | 181 | case DeviceState::SearchingForTag: |
| @@ -264,7 +266,7 @@ private: | |||
| 264 | 266 | ||
| 265 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 267 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 266 | rb.Push(RESULT_SUCCESS); | 268 | rb.Push(RESULT_SUCCESS); |
| 267 | rb.PushCopyObjects(availability_change_event); | 269 | rb.PushCopyObjects(availability_change_event.readable); |
| 268 | } | 270 | } |
| 269 | 271 | ||
| 270 | void GetRegisterInfo(Kernel::HLERequestContext& ctx) { | 272 | void GetRegisterInfo(Kernel::HLERequestContext& ctx) { |
| @@ -319,8 +321,8 @@ private: | |||
| 319 | const u32 npad_id{0}; // Player 1 controller | 321 | const u32 npad_id{0}; // Player 1 controller |
| 320 | State state{State::NonInitialized}; | 322 | State state{State::NonInitialized}; |
| 321 | DeviceState device_state{DeviceState::Initialized}; | 323 | DeviceState device_state{DeviceState::Initialized}; |
| 322 | Kernel::SharedPtr<Kernel::Event> deactivate_event; | 324 | Kernel::EventPair deactivate_event; |
| 323 | Kernel::SharedPtr<Kernel::Event> availability_change_event; | 325 | Kernel::EventPair availability_change_event; |
| 324 | const Module::Interface& nfp_interface; | 326 | const Module::Interface& nfp_interface; |
| 325 | }; | 327 | }; |
| 326 | 328 | ||
| @@ -339,12 +341,14 @@ bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) { | |||
| 339 | } | 341 | } |
| 340 | 342 | ||
| 341 | std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); | 343 | std::memcpy(&amiibo, buffer.data(), sizeof(amiibo)); |
| 342 | nfc_tag_load->Signal(); | 344 | nfc_tag_load.writable->Signal(); |
| 343 | return true; | 345 | return true; |
| 344 | } | 346 | } |
| 345 | const Kernel::SharedPtr<Kernel::Event>& Module::Interface::GetNFCEvent() const { | 347 | |
| 346 | return nfc_tag_load; | 348 | const Kernel::SharedPtr<Kernel::ReadableEvent>& Module::Interface::GetNFCEvent() const { |
| 349 | return nfc_tag_load.readable; | ||
| 347 | } | 350 | } |
| 351 | |||
| 348 | const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const { | 352 | const Module::Interface::AmiiboFile& Module::Interface::GetAmiiboBuffer() const { |
| 349 | return amiibo; | 353 | return amiibo; |
| 350 | } | 354 | } |
diff --git a/src/core/hle/service/nfp/nfp.h b/src/core/hle/service/nfp/nfp.h index 5c0ae8a54..a1817e991 100644 --- a/src/core/hle/service/nfp/nfp.h +++ b/src/core/hle/service/nfp/nfp.h | |||
| @@ -6,7 +6,8 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <vector> | 8 | #include <vector> |
| 9 | #include "core/hle/kernel/event.h" | 9 | #include "core/hle/kernel/readable_event.h" |
| 10 | #include "core/hle/kernel/writable_event.h" | ||
| 10 | #include "core/hle/service/service.h" | 11 | #include "core/hle/service/service.h" |
| 11 | 12 | ||
| 12 | namespace Service::NFP { | 13 | namespace Service::NFP { |
| @@ -33,11 +34,11 @@ public: | |||
| 33 | 34 | ||
| 34 | void CreateUserInterface(Kernel::HLERequestContext& ctx); | 35 | void CreateUserInterface(Kernel::HLERequestContext& ctx); |
| 35 | bool LoadAmiibo(const std::vector<u8>& buffer); | 36 | bool LoadAmiibo(const std::vector<u8>& buffer); |
| 36 | const Kernel::SharedPtr<Kernel::Event>& GetNFCEvent() const; | 37 | const Kernel::SharedPtr<Kernel::ReadableEvent>& GetNFCEvent() const; |
| 37 | const AmiiboFile& GetAmiiboBuffer() const; | 38 | const AmiiboFile& GetAmiiboBuffer() const; |
| 38 | 39 | ||
| 39 | private: | 40 | private: |
| 40 | Kernel::SharedPtr<Kernel::Event> nfc_tag_load{}; | 41 | Kernel::EventPair nfc_tag_load{}; |
| 41 | AmiiboFile amiibo{}; | 42 | AmiiboFile amiibo{}; |
| 42 | 43 | ||
| 43 | protected: | 44 | protected: |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index dee391201..60479bb45 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #include "core/core.h" | 5 | #include "core/core.h" |
| 6 | #include "core/hle/ipc_helpers.h" | 6 | #include "core/hle/ipc_helpers.h" |
| 7 | #include "core/hle/kernel/event.h" | 7 | #include "core/hle/kernel/kernel.h" |
| 8 | #include "core/hle/kernel/readable_event.h" | ||
| 9 | #include "core/hle/kernel/writable_event.h" | ||
| 8 | #include "core/hle/service/nifm/nifm.h" | 10 | #include "core/hle/service/nifm/nifm.h" |
| 9 | #include "core/hle/service/service.h" | 11 | #include "core/hle/service/service.h" |
| 10 | 12 | ||
| @@ -56,8 +58,10 @@ public: | |||
| 56 | RegisterHandlers(functions); | 58 | RegisterHandlers(functions); |
| 57 | 59 | ||
| 58 | auto& kernel = Core::System::GetInstance().Kernel(); | 60 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 59 | event1 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event1"); | 61 | event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, |
| 60 | event2 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event2"); | 62 | "IRequest:Event1"); |
| 63 | event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, | ||
| 64 | "IRequest:Event2"); | ||
| 61 | } | 65 | } |
| 62 | 66 | ||
| 63 | private: | 67 | private: |
| @@ -88,7 +92,7 @@ private: | |||
| 88 | 92 | ||
| 89 | IPC::ResponseBuilder rb{ctx, 2, 2}; | 93 | IPC::ResponseBuilder rb{ctx, 2, 2}; |
| 90 | rb.Push(RESULT_SUCCESS); | 94 | rb.Push(RESULT_SUCCESS); |
| 91 | rb.PushCopyObjects(event1, event2); | 95 | rb.PushCopyObjects(event1.readable, event2.readable); |
| 92 | } | 96 | } |
| 93 | 97 | ||
| 94 | void Cancel(Kernel::HLERequestContext& ctx) { | 98 | void Cancel(Kernel::HLERequestContext& ctx) { |
| @@ -105,7 +109,7 @@ private: | |||
| 105 | rb.Push(RESULT_SUCCESS); | 109 | rb.Push(RESULT_SUCCESS); |
| 106 | } | 110 | } |
| 107 | 111 | ||
| 108 | Kernel::SharedPtr<Kernel::Event> event1, event2; | 112 | Kernel::EventPair event1, event2; |
| 109 | }; | 113 | }; |
| 110 | 114 | ||
| 111 | class INetworkProfile final : public ServiceFramework<INetworkProfile> { | 115 | class INetworkProfile final : public ServiceFramework<INetworkProfile> { |
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 1bbccd444..0dabcd23b 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp | |||
| @@ -6,7 +6,9 @@ | |||
| 6 | #include <ctime> | 6 | #include <ctime> |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/event.h" | 9 | #include "core/hle/kernel/kernel.h" |
| 10 | #include "core/hle/kernel/readable_event.h" | ||
| 11 | #include "core/hle/kernel/writable_event.h" | ||
| 10 | #include "core/hle/service/nim/nim.h" | 12 | #include "core/hle/service/nim/nim.h" |
| 11 | #include "core/hle/service/service.h" | 13 | #include "core/hle/service/service.h" |
| 12 | #include "core/hle/service/sm/sm.h" | 14 | #include "core/hle/service/sm/sm.h" |
| @@ -138,19 +140,18 @@ public: | |||
| 138 | RegisterHandlers(functions); | 140 | RegisterHandlers(functions); |
| 139 | 141 | ||
| 140 | auto& kernel = Core::System::GetInstance().Kernel(); | 142 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 141 | finished_event = | 143 | finished_event = Kernel::WritableEvent::CreateEventPair( |
| 142 | Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, | 144 | kernel, Kernel::ResetType::OneShot, |
| 143 | "IEnsureNetworkClockAvailabilityService:FinishEvent"); | 145 | "IEnsureNetworkClockAvailabilityService:FinishEvent"); |
| 144 | } | 146 | } |
| 145 | 147 | ||
| 146 | private: | 148 | private: |
| 147 | Kernel::SharedPtr<Kernel::Event> finished_event; | 149 | Kernel::EventPair finished_event; |
| 148 | 150 | ||
| 149 | void StartTask(Kernel::HLERequestContext& ctx) { | 151 | void StartTask(Kernel::HLERequestContext& ctx) { |
| 150 | // No need to connect to the internet, just finish the task straight away. | 152 | // No need to connect to the internet, just finish the task straight away. |
| 151 | LOG_DEBUG(Service_NIM, "called"); | 153 | LOG_DEBUG(Service_NIM, "called"); |
| 152 | 154 | finished_event.writable->Signal(); | |
| 153 | finished_event->Signal(); | ||
| 154 | IPC::ResponseBuilder rb{ctx, 2}; | 155 | IPC::ResponseBuilder rb{ctx, 2}; |
| 155 | rb.Push(RESULT_SUCCESS); | 156 | rb.Push(RESULT_SUCCESS); |
| 156 | } | 157 | } |
| @@ -160,7 +161,7 @@ private: | |||
| 160 | 161 | ||
| 161 | IPC::ResponseBuilder rb{ctx, 2, 1}; | 162 | IPC::ResponseBuilder rb{ctx, 2, 1}; |
| 162 | rb.Push(RESULT_SUCCESS); | 163 | rb.Push(RESULT_SUCCESS); |
| 163 | rb.PushCopyObjects(finished_event); | 164 | rb.PushCopyObjects(finished_event.readable); |
| 164 | } | 165 | } |
| 165 | 166 | ||
| 166 | void GetResult(Kernel::HLERequestContext& ctx) { | 167 | void GetResult(Kernel::HLERequestContext& ctx) { |
| @@ -172,8 +173,7 @@ private: | |||
| 172 | 173 | ||
| 173 | void Cancel(Kernel::HLERequestContext& ctx) { | 174 | void Cancel(Kernel::HLERequestContext& ctx) { |
| 174 | LOG_DEBUG(Service_NIM, "called"); | 175 | LOG_DEBUG(Service_NIM, "called"); |
| 175 | 176 | finished_event.writable->Clear(); | |
| 176 | finished_event->Clear(); | ||
| 177 | IPC::ResponseBuilder rb{ctx, 2}; | 177 | IPC::ResponseBuilder rb{ctx, 2}; |
| 178 | rb.Push(RESULT_SUCCESS); | 178 | rb.Push(RESULT_SUCCESS); |
| 179 | } | 179 | } |
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index ff76e0524..3b9ab4b14 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp | |||
| @@ -6,7 +6,9 @@ | |||
| 6 | #include "common/logging/log.h" | 6 | #include "common/logging/log.h" |
| 7 | #include "core/core.h" | 7 | #include "core/core.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/kernel/event.h" | 9 | #include "core/hle/kernel/kernel.h" |
| 10 | #include "core/hle/kernel/readable_event.h" | ||
| 11 | #include "core/hle/kernel/writable_event.h" | ||
| 10 | #include "core/hle/service/nvdrv/interface.h" | 12 | #include "core/hle/service/nvdrv/interface.h" |
| 11 | #include "core/hle/service/nvdrv/nvdrv.h" | 13 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 12 | 14 | ||
| @@ -69,7 +71,7 @@ void NVDRV::QueryEvent(Kernel::HLERequestContext& ctx) { | |||
| 69 | 71 | ||
| 70 | IPC::ResponseBuilder rb{ctx, 3, 1}; | 72 | IPC::ResponseBuilder rb{ctx, 3, 1}; |
| 71 | rb.Push(RESULT_SUCCESS); | 73 | rb.Push(RESULT_SUCCESS); |
| 72 | rb.PushCopyObjects(query_event); | 74 | rb.PushCopyObjects(query_event.readable); |
| 73 | rb.Push<u32>(0); | 75 | rb.Push<u32>(0); |
| 74 | } | 76 | } |
| 75 | 77 | ||
| @@ -127,7 +129,8 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) | |||
| 127 | RegisterHandlers(functions); | 129 | RegisterHandlers(functions); |
| 128 | 130 | ||
| 129 | auto& kernel = Core::System::GetInstance().Kernel(); | 131 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 130 | query_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "NVDRV::query_event"); | 132 | query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, |
| 133 | "NVDRV::query_event"); | ||
| 131 | } | 134 | } |
| 132 | 135 | ||
| 133 | NVDRV::~NVDRV() = default; | 136 | NVDRV::~NVDRV() = default; |
diff --git a/src/core/hle/service/nvdrv/interface.h b/src/core/hle/service/nvdrv/interface.h index 5a1e4baa7..fe311b069 100644 --- a/src/core/hle/service/nvdrv/interface.h +++ b/src/core/hle/service/nvdrv/interface.h | |||
| @@ -5,10 +5,13 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include "core/hle/kernel/event.h" | ||
| 9 | #include "core/hle/service/nvdrv/nvdrv.h" | 8 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 10 | #include "core/hle/service/service.h" | 9 | #include "core/hle/service/service.h" |
| 11 | 10 | ||
| 11 | namespace Kernel { | ||
| 12 | class WritableEvent; | ||
| 13 | } | ||
| 14 | |||
| 12 | namespace Service::Nvidia { | 15 | namespace Service::Nvidia { |
| 13 | 16 | ||
| 14 | class NVDRV final : public ServiceFramework<NVDRV> { | 17 | class NVDRV final : public ServiceFramework<NVDRV> { |
| @@ -31,7 +34,7 @@ private: | |||
| 31 | 34 | ||
| 32 | u64 pid{}; | 35 | u64 pid{}; |
| 33 | 36 | ||
| 34 | Kernel::SharedPtr<Kernel::Event> query_event; | 37 | Kernel::EventPair query_event; |
| 35 | }; | 38 | }; |
| 36 | 39 | ||
| 37 | } // namespace Service::Nvidia | 40 | } // namespace Service::Nvidia |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 172a1a441..fc07d9bb8 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp | |||
| @@ -7,14 +7,17 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "common/logging/log.h" | 8 | #include "common/logging/log.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/kernel/kernel.h" | ||
| 11 | #include "core/hle/kernel/readable_event.h" | ||
| 12 | #include "core/hle/kernel/writable_event.h" | ||
| 10 | #include "core/hle/service/nvflinger/buffer_queue.h" | 13 | #include "core/hle/service/nvflinger/buffer_queue.h" |
| 11 | 14 | ||
| 12 | namespace Service::NVFlinger { | 15 | namespace Service::NVFlinger { |
| 13 | 16 | ||
| 14 | BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { | 17 | BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { |
| 15 | auto& kernel = Core::System::GetInstance().Kernel(); | 18 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 16 | buffer_wait_event = | 19 | buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, |
| 17 | Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "BufferQueue NativeHandle"); | 20 | "BufferQueue NativeHandle"); |
| 18 | } | 21 | } |
| 19 | 22 | ||
| 20 | BufferQueue::~BufferQueue() = default; | 23 | BufferQueue::~BufferQueue() = default; |
| @@ -28,7 +31,7 @@ void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) | |||
| 28 | buffer.status = Buffer::Status::Free; | 31 | buffer.status = Buffer::Status::Free; |
| 29 | 32 | ||
| 30 | queue.emplace_back(buffer); | 33 | queue.emplace_back(buffer); |
| 31 | buffer_wait_event->Signal(); | 34 | buffer_wait_event.writable->Signal(); |
| 32 | } | 35 | } |
| 33 | 36 | ||
| 34 | std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) { | 37 | std::optional<u32> BufferQueue::DequeueBuffer(u32 width, u32 height) { |
| @@ -87,7 +90,7 @@ void BufferQueue::ReleaseBuffer(u32 slot) { | |||
| 87 | ASSERT(itr->status == Buffer::Status::Acquired); | 90 | ASSERT(itr->status == Buffer::Status::Acquired); |
| 88 | itr->status = Buffer::Status::Free; | 91 | itr->status = Buffer::Status::Free; |
| 89 | 92 | ||
| 90 | buffer_wait_event->Signal(); | 93 | buffer_wait_event.writable->Signal(); |
| 91 | } | 94 | } |
| 92 | 95 | ||
| 93 | u32 BufferQueue::Query(QueryType type) { | 96 | u32 BufferQueue::Query(QueryType type) { |
| @@ -104,4 +107,12 @@ u32 BufferQueue::Query(QueryType type) { | |||
| 104 | return 0; | 107 | return 0; |
| 105 | } | 108 | } |
| 106 | 109 | ||
| 110 | Kernel::SharedPtr<Kernel::WritableEvent> BufferQueue::GetWritableBufferWaitEvent() const { | ||
| 111 | return buffer_wait_event.writable; | ||
| 112 | } | ||
| 113 | |||
| 114 | Kernel::SharedPtr<Kernel::ReadableEvent> BufferQueue::GetBufferWaitEvent() const { | ||
| 115 | return buffer_wait_event.readable; | ||
| 116 | } | ||
| 117 | |||
| 107 | } // namespace Service::NVFlinger | 118 | } // namespace Service::NVFlinger |
diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 8cff5eb71..b171f256c 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h | |||
| @@ -10,7 +10,8 @@ | |||
| 10 | #include "common/common_funcs.h" | 10 | #include "common/common_funcs.h" |
| 11 | #include "common/math_util.h" | 11 | #include "common/math_util.h" |
| 12 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 13 | #include "core/hle/kernel/event.h" | 13 | #include "core/hle/kernel/object.h" |
| 14 | #include "core/hle/kernel/writable_event.h" | ||
| 14 | 15 | ||
| 15 | namespace CoreTiming { | 16 | namespace CoreTiming { |
| 16 | struct EventType; | 17 | struct EventType; |
| @@ -86,16 +87,16 @@ public: | |||
| 86 | return id; | 87 | return id; |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 89 | Kernel::SharedPtr<Kernel::Event> GetBufferWaitEvent() const { | 90 | Kernel::SharedPtr<Kernel::WritableEvent> GetWritableBufferWaitEvent() const; |
| 90 | return buffer_wait_event; | 91 | |
| 91 | } | 92 | Kernel::SharedPtr<Kernel::ReadableEvent> GetBufferWaitEvent() const; |
| 92 | 93 | ||
| 93 | private: | 94 | private: |
| 94 | u32 id; | 95 | u32 id; |
| 95 | u64 layer_id; | 96 | u64 layer_id; |
| 96 | 97 | ||
| 97 | std::vector<Buffer> queue; | 98 | std::vector<Buffer> queue; |
| 98 | Kernel::SharedPtr<Kernel::Event> buffer_wait_event; | 99 | Kernel::EventPair buffer_wait_event; |
| 99 | }; | 100 | }; |
| 100 | 101 | ||
| 101 | } // namespace Service::NVFlinger | 102 | } // namespace Service::NVFlinger |
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 214e6d1b3..05af2d593 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -13,6 +13,9 @@ | |||
| 13 | #include "core/core.h" | 13 | #include "core/core.h" |
| 14 | #include "core/core_timing.h" | 14 | #include "core/core_timing.h" |
| 15 | #include "core/core_timing_util.h" | 15 | #include "core/core_timing_util.h" |
| 16 | #include "core/hle/kernel/kernel.h" | ||
| 17 | #include "core/hle/kernel/readable_event.h" | ||
| 18 | #include "core/hle/kernel/writable_event.h" | ||
| 16 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | 19 | #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" |
| 17 | #include "core/hle/service/nvdrv/nvdrv.h" | 20 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 18 | #include "core/hle/service/nvflinger/buffer_queue.h" | 21 | #include "core/hle/service/nvflinger/buffer_queue.h" |
| @@ -83,9 +86,8 @@ u32 NVFlinger::GetBufferQueueId(u64 display_id, u64 layer_id) { | |||
| 83 | return layer.buffer_queue->GetId(); | 86 | return layer.buffer_queue->GetId(); |
| 84 | } | 87 | } |
| 85 | 88 | ||
| 86 | Kernel::SharedPtr<Kernel::Event> NVFlinger::GetVsyncEvent(u64 display_id) { | 89 | Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) { |
| 87 | const auto& display = GetDisplay(display_id); | 90 | return GetDisplay(display_id).vsync_event.readable; |
| 88 | return display.vsync_event; | ||
| 89 | } | 91 | } |
| 90 | 92 | ||
| 91 | std::shared_ptr<BufferQueue> NVFlinger::GetBufferQueue(u32 id) const { | 93 | std::shared_ptr<BufferQueue> NVFlinger::GetBufferQueue(u32 id) const { |
| @@ -117,7 +119,7 @@ Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) { | |||
| 117 | void NVFlinger::Compose() { | 119 | void NVFlinger::Compose() { |
| 118 | for (auto& display : displays) { | 120 | for (auto& display : displays) { |
| 119 | // Trigger vsync for this display at the end of drawing | 121 | // Trigger vsync for this display at the end of drawing |
| 120 | SCOPE_EXIT({ display.vsync_event->Signal(); }); | 122 | SCOPE_EXIT({ display.vsync_event.writable->Signal(); }); |
| 121 | 123 | ||
| 122 | // Don't do anything for displays without layers. | 124 | // Don't do anything for displays without layers. |
| 123 | if (display.layers.empty()) | 125 | if (display.layers.empty()) |
| @@ -164,7 +166,8 @@ Layer::~Layer() = default; | |||
| 164 | 166 | ||
| 165 | Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { | 167 | Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { |
| 166 | auto& kernel = Core::System::GetInstance().Kernel(); | 168 | auto& kernel = Core::System::GetInstance().Kernel(); |
| 167 | vsync_event = Kernel::Event::Create(kernel, Kernel::ResetType::Pulse, "Display VSync Event"); | 169 | vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Pulse, |
| 170 | fmt::format("Display VSync Event {}", id)); | ||
| 168 | } | 171 | } |
| 169 | 172 | ||
| 170 | Display::~Display() = default; | 173 | Display::~Display() = default; |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 3dc69e69b..9abba555b 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -10,12 +10,17 @@ | |||
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | 11 | ||
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/hle/kernel/event.h" | 13 | #include "core/hle/kernel/object.h" |
| 14 | 14 | ||
| 15 | namespace CoreTiming { | 15 | namespace CoreTiming { |
| 16 | struct EventType; | 16 | struct EventType; |
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | namespace Kernel { | ||
| 20 | class ReadableEvent; | ||
| 21 | class WritableEvent; | ||
| 22 | } // namespace Kernel | ||
| 23 | |||
| 19 | namespace Service::Nvidia { | 24 | namespace Service::Nvidia { |
| 20 | class Module; | 25 | class Module; |
| 21 | } | 26 | } |
| @@ -40,7 +45,7 @@ struct Display { | |||
| 40 | std::string name; | 45 | std::string name; |
| 41 | 46 | ||
| 42 | std::vector<Layer> layers; | 47 | std::vector<Layer> layers; |
| 43 | Kernel::SharedPtr<Kernel::Event> vsync_event; | 48 | Kernel::EventPair vsync_event; |
| 44 | }; | 49 | }; |
| 45 | 50 | ||
| 46 | class NVFlinger final { | 51 | class NVFlinger final { |
| @@ -61,7 +66,7 @@ public: | |||
| 61 | u32 GetBufferQueueId(u64 display_id, u64 layer_id); | 66 | u32 GetBufferQueueId(u64 display_id, u64 layer_id); |
| 62 | 67 | ||
| 63 | /// Gets the vsync event for the specified display. | 68 | /// Gets the vsync event for the specified display. |
| 64 | Kernel::SharedPtr<Kernel::Event> GetVsyncEvent(u64 display_id); | 69 | Kernel::SharedPtr<Kernel::ReadableEvent> GetVsyncEvent(u64 display_id); |
| 65 | 70 | ||
| 66 | /// Obtains a buffer queue identified by the id. | 71 | /// Obtains a buffer queue identified by the id. |
| 67 | std::shared_ptr<BufferQueue> GetBufferQueue(u32 id) const; | 72 | std::shared_ptr<BufferQueue> GetBufferQueue(u32 id) const; |
diff --git a/src/core/hle/service/usb/usb.cpp b/src/core/hle/service/usb/usb.cpp index f082a63bc..58a9845fc 100644 --- a/src/core/hle/service/usb/usb.cpp +++ b/src/core/hle/service/usb/usb.cpp | |||
| @@ -73,7 +73,7 @@ public: | |||
| 73 | {3, nullptr, "Populate"}, | 73 | {3, nullptr, "Populate"}, |
| 74 | {4, nullptr, "PostBufferAsync"}, | 74 | {4, nullptr, "PostBufferAsync"}, |
| 75 | {5, nullptr, "GetXferReport"}, | 75 | {5, nullptr, "GetXferReport"}, |
| 76 | {6, nullptr, "Unknown2"}, | 76 | {6, nullptr, "PostBufferMultiAsync"}, |
| 77 | {7, nullptr, "Unknown3"}, | 77 | {7, nullptr, "Unknown3"}, |
| 78 | {8, nullptr, "Unknown4"}, | 78 | {8, nullptr, "Unknown4"}, |
| 79 | }; | 79 | }; |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 5120abfff..311b0c765 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -18,7 +18,8 @@ | |||
| 18 | #include "common/swap.h" | 18 | #include "common/swap.h" |
| 19 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 20 | #include "core/hle/ipc_helpers.h" | 20 | #include "core/hle/ipc_helpers.h" |
| 21 | #include "core/hle/kernel/event.h" | 21 | #include "core/hle/kernel/readable_event.h" |
| 22 | #include "core/hle/kernel/writable_event.h" | ||
| 22 | #include "core/hle/service/nvdrv/nvdrv.h" | 23 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 23 | #include "core/hle/service/nvflinger/buffer_queue.h" | 24 | #include "core/hle/service/nvflinger/buffer_queue.h" |
| 24 | #include "core/hle/service/nvflinger/nvflinger.h" | 25 | #include "core/hle/service/nvflinger/nvflinger.h" |
| @@ -542,12 +543,14 @@ private: | |||
| 542 | // Repeat TransactParcel DequeueBuffer when a buffer is available | 543 | // Repeat TransactParcel DequeueBuffer when a buffer is available |
| 543 | auto buffer_queue = nv_flinger->GetBufferQueue(id); | 544 | auto buffer_queue = nv_flinger->GetBufferQueue(id); |
| 544 | std::optional<u32> slot = buffer_queue->DequeueBuffer(width, height); | 545 | std::optional<u32> slot = buffer_queue->DequeueBuffer(width, height); |
| 546 | ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer."); | ||
| 547 | |||
| 545 | IGBPDequeueBufferResponseParcel response{*slot}; | 548 | IGBPDequeueBufferResponseParcel response{*slot}; |
| 546 | ctx.WriteBuffer(response.Serialize()); | 549 | ctx.WriteBuffer(response.Serialize()); |
| 547 | IPC::ResponseBuilder rb{ctx, 2}; | 550 | IPC::ResponseBuilder rb{ctx, 2}; |
| 548 | rb.Push(RESULT_SUCCESS); | 551 | rb.Push(RESULT_SUCCESS); |
| 549 | }, | 552 | }, |
| 550 | buffer_queue->GetBufferWaitEvent()); | 553 | buffer_queue->GetWritableBufferWaitEvent()); |
| 551 | } | 554 | } |
| 552 | } else if (transaction == TransactionId::RequestBuffer) { | 555 | } else if (transaction == TransactionId::RequestBuffer) { |
| 553 | IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()}; | 556 | IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()}; |
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 8518dddcb..ac04d72d7 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp | |||
| @@ -7,7 +7,6 @@ | |||
| 7 | #include "common/common_funcs.h" | 7 | #include "common/common_funcs.h" |
| 8 | #include "common/file_util.h" | 8 | #include "common/file_util.h" |
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/core.h" | ||
| 11 | #include "core/file_sys/content_archive.h" | 10 | #include "core/file_sys/content_archive.h" |
| 12 | #include "core/file_sys/control_metadata.h" | 11 | #include "core/file_sys/control_metadata.h" |
| 13 | #include "core/file_sys/patch_manager.h" | 12 | #include "core/file_sys/patch_manager.h" |
| @@ -146,7 +145,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(Kernel::Process& process) | |||
| 146 | const VAddr load_addr = next_load_addr; | 145 | const VAddr load_addr = next_load_addr; |
| 147 | const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; | 146 | const bool should_pass_arguments = std::strcmp(module, "rtld") == 0; |
| 148 | const auto tentative_next_load_addr = | 147 | const auto tentative_next_load_addr = |
| 149 | AppLoader_NSO::LoadModule(*module_file, load_addr, should_pass_arguments, pm); | 148 | AppLoader_NSO::LoadModule(process, *module_file, load_addr, should_pass_arguments, pm); |
| 150 | if (!tentative_next_load_addr) { | 149 | if (!tentative_next_load_addr) { |
| 151 | return ResultStatus::ErrorLoadingNSO; | 150 | return ResultStatus::ErrorLoadingNSO; |
| 152 | } | 151 | } |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index fbbd6b0de..4fad0c0dd 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "common/file_util.h" | 10 | #include "common/file_util.h" |
| 11 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| 12 | #include "common/swap.h" | 12 | #include "common/swap.h" |
| 13 | #include "core/core.h" | ||
| 14 | #include "core/file_sys/control_metadata.h" | 13 | #include "core/file_sys/control_metadata.h" |
| 15 | #include "core/file_sys/romfs_factory.h" | 14 | #include "core/file_sys/romfs_factory.h" |
| 16 | #include "core/file_sys/vfs_offset.h" | 15 | #include "core/file_sys/vfs_offset.h" |
| @@ -129,9 +128,8 @@ static constexpr u32 PageAlignSize(u32 size) { | |||
| 129 | return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; | 128 | return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; |
| 130 | } | 129 | } |
| 131 | 130 | ||
| 132 | /*static*/ bool AppLoader_NRO::LoadNro(const std::vector<u8>& data, const std::string& name, | 131 | static bool LoadNroImpl(Kernel::Process& process, const std::vector<u8>& data, |
| 133 | VAddr load_base) { | 132 | const std::string& name, VAddr load_base) { |
| 134 | |||
| 135 | if (data.size() < sizeof(NroHeader)) { | 133 | if (data.size() < sizeof(NroHeader)) { |
| 136 | return {}; | 134 | return {}; |
| 137 | } | 135 | } |
| @@ -189,7 +187,7 @@ static constexpr u32 PageAlignSize(u32 size) { | |||
| 189 | 187 | ||
| 190 | // Load codeset for current process | 188 | // Load codeset for current process |
| 191 | codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image)); | 189 | codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image)); |
| 192 | Core::CurrentProcess()->LoadModule(std::move(codeset), load_base); | 190 | process.LoadModule(std::move(codeset), load_base); |
| 193 | 191 | ||
| 194 | // Register module with GDBStub | 192 | // Register module with GDBStub |
| 195 | GDBStub::RegisterModule(name, load_base, load_base); | 193 | GDBStub::RegisterModule(name, load_base, load_base); |
| @@ -197,8 +195,9 @@ static constexpr u32 PageAlignSize(u32 size) { | |||
| 197 | return true; | 195 | return true; |
| 198 | } | 196 | } |
| 199 | 197 | ||
| 200 | bool AppLoader_NRO::LoadNro(const FileSys::VfsFile& file, VAddr load_base) { | 198 | bool AppLoader_NRO::LoadNro(Kernel::Process& process, const FileSys::VfsFile& file, |
| 201 | return AppLoader_NRO::LoadNro(file.ReadAllBytes(), file.GetName(), load_base); | 199 | VAddr load_base) { |
| 200 | return LoadNroImpl(process, file.ReadAllBytes(), file.GetName(), load_base); | ||
| 202 | } | 201 | } |
| 203 | 202 | ||
| 204 | ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { | 203 | ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { |
| @@ -209,7 +208,7 @@ ResultStatus AppLoader_NRO::Load(Kernel::Process& process) { | |||
| 209 | // Load NRO | 208 | // Load NRO |
| 210 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); | 209 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); |
| 211 | 210 | ||
| 212 | if (!LoadNro(*file, base_address)) { | 211 | if (!LoadNro(process, *file, base_address)) { |
| 213 | return ResultStatus::ErrorLoadingNRO; | 212 | return ResultStatus::ErrorLoadingNRO; |
| 214 | } | 213 | } |
| 215 | 214 | ||
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h index 3e6959302..6deff3a51 100644 --- a/src/core/loader/nro.h +++ b/src/core/loader/nro.h | |||
| @@ -14,6 +14,10 @@ namespace FileSys { | |||
| 14 | class NACP; | 14 | class NACP; |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | namespace Kernel { | ||
| 18 | class Process; | ||
| 19 | } | ||
| 20 | |||
| 17 | namespace Loader { | 21 | namespace Loader { |
| 18 | 22 | ||
| 19 | /// Loads an NRO file | 23 | /// Loads an NRO file |
| @@ -41,10 +45,8 @@ public: | |||
| 41 | ResultStatus ReadTitle(std::string& title) override; | 45 | ResultStatus ReadTitle(std::string& title) override; |
| 42 | bool IsRomFSUpdatable() const override; | 46 | bool IsRomFSUpdatable() const override; |
| 43 | 47 | ||
| 44 | static bool LoadNro(const std::vector<u8>& data, const std::string& name, VAddr load_base); | ||
| 45 | |||
| 46 | private: | 48 | private: |
| 47 | bool LoadNro(const FileSys::VfsFile& file, VAddr load_base); | 49 | bool LoadNro(Kernel::Process& process, const FileSys::VfsFile& file, VAddr load_base); |
| 48 | 50 | ||
| 49 | std::vector<u8> icon_data; | 51 | std::vector<u8> icon_data; |
| 50 | std::unique_ptr<FileSys::NACP> nacp; | 52 | std::unique_ptr<FileSys::NACP> nacp; |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index aaf006309..6ded0b707 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -9,7 +9,6 @@ | |||
| 9 | #include "common/file_util.h" | 9 | #include "common/file_util.h" |
| 10 | #include "common/logging/log.h" | 10 | #include "common/logging/log.h" |
| 11 | #include "common/swap.h" | 11 | #include "common/swap.h" |
| 12 | #include "core/core.h" | ||
| 13 | #include "core/file_sys/patch_manager.h" | 12 | #include "core/file_sys/patch_manager.h" |
| 14 | #include "core/gdbstub/gdbstub.h" | 13 | #include "core/gdbstub/gdbstub.h" |
| 15 | #include "core/hle/kernel/process.h" | 14 | #include "core/hle/kernel/process.h" |
| @@ -93,7 +92,8 @@ static constexpr u32 PageAlignSize(u32 size) { | |||
| 93 | return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; | 92 | return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK; |
| 94 | } | 93 | } |
| 95 | 94 | ||
| 96 | std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAddr load_base, | 95 | std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::Process& process, |
| 96 | const FileSys::VfsFile& file, VAddr load_base, | ||
| 97 | bool should_pass_arguments, | 97 | bool should_pass_arguments, |
| 98 | std::optional<FileSys::PatchManager> pm) { | 98 | std::optional<FileSys::PatchManager> pm) { |
| 99 | if (file.GetSize() < sizeof(NsoHeader)) | 99 | if (file.GetSize() < sizeof(NsoHeader)) |
| @@ -166,7 +166,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAd | |||
| 166 | 166 | ||
| 167 | // Load codeset for current process | 167 | // Load codeset for current process |
| 168 | codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image)); | 168 | codeset.memory = std::make_shared<std::vector<u8>>(std::move(program_image)); |
| 169 | Core::CurrentProcess()->LoadModule(std::move(codeset), load_base); | 169 | process.LoadModule(std::move(codeset), load_base); |
| 170 | 170 | ||
| 171 | // Register module with GDBStub | 171 | // Register module with GDBStub |
| 172 | GDBStub::RegisterModule(file.GetName(), load_base, load_base); | 172 | GDBStub::RegisterModule(file.GetName(), load_base, load_base); |
| @@ -181,7 +181,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::Process& process) { | |||
| 181 | 181 | ||
| 182 | // Load module | 182 | // Load module |
| 183 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); | 183 | const VAddr base_address = process.VMManager().GetCodeRegionBaseAddress(); |
| 184 | if (!LoadModule(*file, base_address, true)) { | 184 | if (!LoadModule(process, *file, base_address, true)) { |
| 185 | return ResultStatus::ErrorLoadingNSO; | 185 | return ResultStatus::ErrorLoadingNSO; |
| 186 | } | 186 | } |
| 187 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); | 187 | LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), base_address); |
diff --git a/src/core/loader/nso.h b/src/core/loader/nso.h index 433306139..0c1defbb6 100644 --- a/src/core/loader/nso.h +++ b/src/core/loader/nso.h | |||
| @@ -10,6 +10,10 @@ | |||
| 10 | #include "core/loader/linker.h" | 10 | #include "core/loader/linker.h" |
| 11 | #include "core/loader/loader.h" | 11 | #include "core/loader/loader.h" |
| 12 | 12 | ||
| 13 | namespace Kernel { | ||
| 14 | class Process; | ||
| 15 | } | ||
| 16 | |||
| 13 | namespace Loader { | 17 | namespace Loader { |
| 14 | 18 | ||
| 15 | constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000; | 19 | constexpr u64 NSO_ARGUMENT_DATA_ALLOCATION_SIZE = 0x9000; |
| @@ -37,8 +41,8 @@ public: | |||
| 37 | return IdentifyType(file); | 41 | return IdentifyType(file); |
| 38 | } | 42 | } |
| 39 | 43 | ||
| 40 | static std::optional<VAddr> LoadModule(const FileSys::VfsFile& file, VAddr load_base, | 44 | static std::optional<VAddr> LoadModule(Kernel::Process& process, const FileSys::VfsFile& file, |
| 41 | bool should_pass_arguments, | 45 | VAddr load_base, bool should_pass_arguments, |
| 42 | std::optional<FileSys::PatchManager> pm = {}); | 46 | std::optional<FileSys::PatchManager> pm = {}); |
| 43 | 47 | ||
| 44 | ResultStatus Load(Kernel::Process& process) override; | 48 | ResultStatus Load(Kernel::Process& process) override; |
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp deleted file mode 100644 index 8b9c548cc..000000000 --- a/src/video_core/command_processor.cpp +++ /dev/null | |||
| @@ -1,142 +0,0 @@ | |||
| 1 | // Copyright 2018 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 <cstddef> | ||
| 7 | #include <memory> | ||
| 8 | #include <utility> | ||
| 9 | #include "common/assert.h" | ||
| 10 | #include "common/logging/log.h" | ||
| 11 | #include "common/microprofile.h" | ||
| 12 | #include "common/vector_math.h" | ||
| 13 | #include "core/memory.h" | ||
| 14 | #include "core/tracer/recorder.h" | ||
| 15 | #include "video_core/command_processor.h" | ||
| 16 | #include "video_core/engines/fermi_2d.h" | ||
| 17 | #include "video_core/engines/kepler_memory.h" | ||
| 18 | #include "video_core/engines/maxwell_3d.h" | ||
| 19 | #include "video_core/engines/maxwell_compute.h" | ||
| 20 | #include "video_core/engines/maxwell_dma.h" | ||
| 21 | #include "video_core/gpu.h" | ||
| 22 | #include "video_core/renderer_base.h" | ||
| 23 | #include "video_core/video_core.h" | ||
| 24 | |||
| 25 | namespace Tegra { | ||
| 26 | |||
| 27 | enum class BufferMethods { | ||
| 28 | BindObject = 0, | ||
| 29 | CountBufferMethods = 0x40, | ||
| 30 | }; | ||
| 31 | |||
| 32 | MICROPROFILE_DEFINE(ProcessCommandLists, "GPU", "Execute command buffer", MP_RGB(128, 128, 192)); | ||
| 33 | |||
| 34 | void GPU::ProcessCommandLists(const std::vector<CommandListHeader>& commands) { | ||
| 35 | MICROPROFILE_SCOPE(ProcessCommandLists); | ||
| 36 | |||
| 37 | // On entering GPU code, assume all memory may be touched by the ARM core. | ||
| 38 | maxwell_3d->dirty_flags.OnMemoryWrite(); | ||
| 39 | |||
| 40 | auto WriteReg = [this](u32 method, u32 subchannel, u32 value, u32 remaining_params) { | ||
| 41 | LOG_TRACE(HW_GPU, | ||
| 42 | "Processing method {:08X} on subchannel {} value " | ||
| 43 | "{:08X} remaining params {}", | ||
| 44 | method, subchannel, value, remaining_params); | ||
| 45 | |||
| 46 | ASSERT(subchannel < bound_engines.size()); | ||
| 47 | |||
| 48 | if (method == static_cast<u32>(BufferMethods::BindObject)) { | ||
| 49 | // Bind the current subchannel to the desired engine id. | ||
| 50 | LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value); | ||
| 51 | bound_engines[subchannel] = static_cast<EngineID>(value); | ||
| 52 | return; | ||
| 53 | } | ||
| 54 | |||
| 55 | if (method < static_cast<u32>(BufferMethods::CountBufferMethods)) { | ||
| 56 | // TODO(Subv): Research and implement these methods. | ||
| 57 | LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented"); | ||
| 58 | return; | ||
| 59 | } | ||
| 60 | |||
| 61 | const EngineID engine = bound_engines[subchannel]; | ||
| 62 | |||
| 63 | switch (engine) { | ||
| 64 | case EngineID::FERMI_TWOD_A: | ||
| 65 | fermi_2d->WriteReg(method, value); | ||
| 66 | break; | ||
| 67 | case EngineID::MAXWELL_B: | ||
| 68 | maxwell_3d->WriteReg(method, value, remaining_params); | ||
| 69 | break; | ||
| 70 | case EngineID::MAXWELL_COMPUTE_B: | ||
| 71 | maxwell_compute->WriteReg(method, value); | ||
| 72 | break; | ||
| 73 | case EngineID::MAXWELL_DMA_COPY_A: | ||
| 74 | maxwell_dma->WriteReg(method, value); | ||
| 75 | break; | ||
| 76 | case EngineID::KEPLER_INLINE_TO_MEMORY_B: | ||
| 77 | kepler_memory->WriteReg(method, value); | ||
| 78 | break; | ||
| 79 | default: | ||
| 80 | UNIMPLEMENTED_MSG("Unimplemented engine"); | ||
| 81 | } | ||
| 82 | }; | ||
| 83 | |||
| 84 | for (auto entry : commands) { | ||
| 85 | Tegra::GPUVAddr address = entry.Address(); | ||
| 86 | u32 size = entry.sz; | ||
| 87 | const std::optional<VAddr> head_address = memory_manager->GpuToCpuAddress(address); | ||
| 88 | VAddr current_addr = *head_address; | ||
| 89 | while (current_addr < *head_address + size * sizeof(CommandHeader)) { | ||
| 90 | const CommandHeader header = {Memory::Read32(current_addr)}; | ||
| 91 | current_addr += sizeof(u32); | ||
| 92 | |||
| 93 | switch (header.mode.Value()) { | ||
| 94 | case SubmissionMode::IncreasingOld: | ||
| 95 | case SubmissionMode::Increasing: { | ||
| 96 | // Increase the method value with each argument. | ||
| 97 | for (unsigned i = 0; i < header.arg_count; ++i) { | ||
| 98 | WriteReg(header.method + i, header.subchannel, Memory::Read32(current_addr), | ||
| 99 | header.arg_count - i - 1); | ||
| 100 | current_addr += sizeof(u32); | ||
| 101 | } | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | case SubmissionMode::NonIncreasingOld: | ||
| 105 | case SubmissionMode::NonIncreasing: { | ||
| 106 | // Use the same method value for all arguments. | ||
| 107 | for (unsigned i = 0; i < header.arg_count; ++i) { | ||
| 108 | WriteReg(header.method, header.subchannel, Memory::Read32(current_addr), | ||
| 109 | header.arg_count - i - 1); | ||
| 110 | current_addr += sizeof(u32); | ||
| 111 | } | ||
| 112 | break; | ||
| 113 | } | ||
| 114 | case SubmissionMode::IncreaseOnce: { | ||
| 115 | ASSERT(header.arg_count.Value() >= 1); | ||
| 116 | |||
| 117 | // Use the original method for the first argument and then the next method for all | ||
| 118 | // other arguments. | ||
| 119 | WriteReg(header.method, header.subchannel, Memory::Read32(current_addr), | ||
| 120 | header.arg_count - 1); | ||
| 121 | current_addr += sizeof(u32); | ||
| 122 | |||
| 123 | for (unsigned i = 1; i < header.arg_count; ++i) { | ||
| 124 | WriteReg(header.method + 1, header.subchannel, Memory::Read32(current_addr), | ||
| 125 | header.arg_count - i - 1); | ||
| 126 | current_addr += sizeof(u32); | ||
| 127 | } | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | case SubmissionMode::Inline: { | ||
| 131 | // The register value is stored in the bits 16-28 as an immediate | ||
| 132 | WriteReg(header.method, header.subchannel, header.inline_data, 0); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | default: | ||
| 136 | UNIMPLEMENTED(); | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | } // namespace Tegra | ||
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index d3b3ed1f0..25bb7604a 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -42,6 +42,7 @@ public: | |||
| 42 | static constexpr std::size_t NumVertexArrays = 32; | 42 | static constexpr std::size_t NumVertexArrays = 32; |
| 43 | static constexpr std::size_t NumVertexAttributes = 32; | 43 | static constexpr std::size_t NumVertexAttributes = 32; |
| 44 | static constexpr std::size_t NumTextureSamplers = 32; | 44 | static constexpr std::size_t NumTextureSamplers = 32; |
| 45 | static constexpr std::size_t NumClipDistances = 8; | ||
| 45 | static constexpr std::size_t MaxShaderProgram = 6; | 46 | static constexpr std::size_t MaxShaderProgram = 6; |
| 46 | static constexpr std::size_t MaxShaderStage = 5; | 47 | static constexpr std::size_t MaxShaderStage = 5; |
| 47 | // Maximum number of const buffers per shader stage. | 48 | // Maximum number of const buffers per shader stage. |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index fd1242333..88c45a423 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -141,6 +141,12 @@ void GPU::CallMethod(const MethodCall& method_call) { | |||
| 141 | return; | 141 | return; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | if (method_call.method < static_cast<u32>(BufferMethods::CountBufferMethods)) { | ||
| 145 | // TODO(Subv): Research and implement these methods. | ||
| 146 | LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented"); | ||
| 147 | return; | ||
| 148 | } | ||
| 149 | |||
| 144 | const EngineID engine = bound_engines[method_call.subchannel]; | 150 | const EngineID engine = bound_engines[method_call.subchannel]; |
| 145 | 151 | ||
| 146 | switch (engine) { | 152 | switch (engine) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index a44bbfae8..9e93bd609 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -88,19 +88,6 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& window, ScreenInfo | |||
| 88 | state.texture_units[i].sampler = texture_samplers[i].sampler.handle; | 88 | state.texture_units[i].sampler = texture_samplers[i].sampler.handle; |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | GLint ext_num; | ||
| 92 | glGetIntegerv(GL_NUM_EXTENSIONS, &ext_num); | ||
| 93 | for (GLint i = 0; i < ext_num; i++) { | ||
| 94 | const std::string_view extension{ | ||
| 95 | reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i))}; | ||
| 96 | |||
| 97 | if (extension == "GL_ARB_direct_state_access") { | ||
| 98 | has_ARB_direct_state_access = true; | ||
| 99 | } else if (extension == "GL_ARB_multi_bind") { | ||
| 100 | has_ARB_multi_bind = true; | ||
| 101 | } | ||
| 102 | } | ||
| 103 | |||
| 104 | OpenGLState::ApplyDefaultState(); | 91 | OpenGLState::ApplyDefaultState(); |
| 105 | 92 | ||
| 106 | // Create render framebuffer | 93 | // Create render framebuffer |
| @@ -295,6 +282,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 295 | // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points. | 282 | // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points. |
| 296 | u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; | 283 | u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage; |
| 297 | u32 current_texture_bindpoint = 0; | 284 | u32 current_texture_bindpoint = 0; |
| 285 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | ||
| 298 | 286 | ||
| 299 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { | 287 | for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { |
| 300 | const auto& shader_config = gpu.regs.shader_config[index]; | 288 | const auto& shader_config = gpu.regs.shader_config[index]; |
| @@ -355,12 +343,22 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | |||
| 355 | current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader, | 343 | current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader, |
| 356 | primitive_mode, current_texture_bindpoint); | 344 | primitive_mode, current_texture_bindpoint); |
| 357 | 345 | ||
| 346 | // Workaround for Intel drivers. | ||
| 347 | // When a clip distance is enabled but not set in the shader it crops parts of the screen | ||
| 348 | // (sometimes it's half the screen, sometimes three quarters). To avoid this, enable the | ||
| 349 | // clip distances only when it's written by a shader stage. | ||
| 350 | for (std::size_t i = 0; i < Maxwell::NumClipDistances; ++i) { | ||
| 351 | clip_distances[i] |= shader->GetShaderEntries().clip_distances[i]; | ||
| 352 | } | ||
| 353 | |||
| 358 | // When VertexA is enabled, we have dual vertex shaders | 354 | // When VertexA is enabled, we have dual vertex shaders |
| 359 | if (program == Maxwell::ShaderProgram::VertexA) { | 355 | if (program == Maxwell::ShaderProgram::VertexA) { |
| 360 | // VertexB was combined with VertexA, so we skip the VertexB iteration | 356 | // VertexB was combined with VertexA, so we skip the VertexB iteration |
| 361 | index++; | 357 | index++; |
| 362 | } | 358 | } |
| 363 | } | 359 | } |
| 360 | |||
| 361 | SyncClipEnabled(clip_distances); | ||
| 364 | } | 362 | } |
| 365 | 363 | ||
| 366 | std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { | 364 | std::size_t RasterizerOpenGL::CalculateVertexArraysSize() const { |
| @@ -443,7 +441,7 @@ void RasterizerOpenGL::ConfigureFramebuffers(OpenGLState& current_state, bool us | |||
| 443 | // TODO(bunnei): Figure out how the below register works. According to envytools, this should be | 441 | // TODO(bunnei): Figure out how the below register works. According to envytools, this should be |
| 444 | // used to enable multiple render targets. However, it is left unset on all games that I have | 442 | // used to enable multiple render targets. However, it is left unset on all games that I have |
| 445 | // tested. | 443 | // tested. |
| 446 | ASSERT_MSG(regs.rt_separate_frag_data == 0, "Unimplemented"); | 444 | UNIMPLEMENTED_IF(regs.rt_separate_frag_data != 0); |
| 447 | 445 | ||
| 448 | // Bind the framebuffer surfaces | 446 | // Bind the framebuffer surfaces |
| 449 | current_state.draw.draw_framebuffer = framebuffer.handle; | 447 | current_state.draw.draw_framebuffer = framebuffer.handle; |
| @@ -642,7 +640,6 @@ void RasterizerOpenGL::DrawArrays() { | |||
| 642 | SyncCullMode(); | 640 | SyncCullMode(); |
| 643 | SyncPrimitiveRestart(); | 641 | SyncPrimitiveRestart(); |
| 644 | SyncScissorTest(state); | 642 | SyncScissorTest(state); |
| 645 | SyncClipEnabled(); | ||
| 646 | // Alpha Testing is synced on shaders. | 643 | // Alpha Testing is synced on shaders. |
| 647 | SyncTransformFeedback(); | 644 | SyncTransformFeedback(); |
| 648 | SyncPointState(); | 645 | SyncPointState(); |
| @@ -1019,20 +1016,23 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { | |||
| 1019 | state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0; | 1016 | state.depth_clamp.near_plane = regs.view_volume_clip_control.depth_clamp_near != 0; |
| 1020 | } | 1017 | } |
| 1021 | 1018 | ||
| 1022 | void RasterizerOpenGL::SyncClipEnabled() { | 1019 | void RasterizerOpenGL::SyncClipEnabled( |
| 1020 | const std::array<bool, Maxwell::Regs::NumClipDistances>& clip_mask) { | ||
| 1021 | |||
| 1023 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; | 1022 | const auto& regs = Core::System::GetInstance().GPU().Maxwell3D().regs; |
| 1024 | state.clip_distance[0] = regs.clip_distance_enabled.c0 != 0; | 1023 | const std::array<bool, Maxwell::Regs::NumClipDistances> reg_state{ |
| 1025 | state.clip_distance[1] = regs.clip_distance_enabled.c1 != 0; | 1024 | regs.clip_distance_enabled.c0 != 0, regs.clip_distance_enabled.c1 != 0, |
| 1026 | state.clip_distance[2] = regs.clip_distance_enabled.c2 != 0; | 1025 | regs.clip_distance_enabled.c2 != 0, regs.clip_distance_enabled.c3 != 0, |
| 1027 | state.clip_distance[3] = regs.clip_distance_enabled.c3 != 0; | 1026 | regs.clip_distance_enabled.c4 != 0, regs.clip_distance_enabled.c5 != 0, |
| 1028 | state.clip_distance[4] = regs.clip_distance_enabled.c4 != 0; | 1027 | regs.clip_distance_enabled.c6 != 0, regs.clip_distance_enabled.c7 != 0}; |
| 1029 | state.clip_distance[5] = regs.clip_distance_enabled.c5 != 0; | 1028 | |
| 1030 | state.clip_distance[6] = regs.clip_distance_enabled.c6 != 0; | 1029 | for (std::size_t i = 0; i < Maxwell::Regs::NumClipDistances; ++i) { |
| 1031 | state.clip_distance[7] = regs.clip_distance_enabled.c7 != 0; | 1030 | state.clip_distance[i] = reg_state[i] && clip_mask[i]; |
| 1031 | } | ||
| 1032 | } | 1032 | } |
| 1033 | 1033 | ||
| 1034 | void RasterizerOpenGL::SyncClipCoef() { | 1034 | void RasterizerOpenGL::SyncClipCoef() { |
| 1035 | UNREACHABLE(); | 1035 | UNIMPLEMENTED(); |
| 1036 | } | 1036 | } |
| 1037 | 1037 | ||
| 1038 | void RasterizerOpenGL::SyncCullMode() { | 1038 | void RasterizerOpenGL::SyncCullMode() { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 7ec9746b1..988fa3e27 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -60,20 +60,6 @@ public: | |||
| 60 | bool AccelerateDrawBatch(bool is_indexed) override; | 60 | bool AccelerateDrawBatch(bool is_indexed) override; |
| 61 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) override; | 61 | void UpdatePagesCachedCount(Tegra::GPUVAddr addr, u64 size, int delta) override; |
| 62 | 62 | ||
| 63 | /// OpenGL shader generated for a given Maxwell register state | ||
| 64 | struct MaxwellShader { | ||
| 65 | /// OpenGL shader resource | ||
| 66 | OGLProgram shader; | ||
| 67 | }; | ||
| 68 | |||
| 69 | struct VertexShader { | ||
| 70 | OGLShader shader; | ||
| 71 | }; | ||
| 72 | |||
| 73 | struct FragmentShader { | ||
| 74 | OGLShader shader; | ||
| 75 | }; | ||
| 76 | |||
| 77 | /// Maximum supported size that a constbuffer can have in bytes. | 63 | /// Maximum supported size that a constbuffer can have in bytes. |
| 78 | static constexpr std::size_t MaxConstbufferSize = 0x10000; | 64 | static constexpr std::size_t MaxConstbufferSize = 0x10000; |
| 79 | static_assert(MaxConstbufferSize % sizeof(GLvec4) == 0, | 65 | static_assert(MaxConstbufferSize % sizeof(GLvec4) == 0, |
| @@ -142,7 +128,8 @@ private: | |||
| 142 | void SyncViewport(OpenGLState& current_state); | 128 | void SyncViewport(OpenGLState& current_state); |
| 143 | 129 | ||
| 144 | /// Syncs the clip enabled status to match the guest state | 130 | /// Syncs the clip enabled status to match the guest state |
| 145 | void SyncClipEnabled(); | 131 | void SyncClipEnabled( |
| 132 | const std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances>& clip_mask); | ||
| 146 | 133 | ||
| 147 | /// Syncs the clip coefficients to match the guest state | 134 | /// Syncs the clip coefficients to match the guest state |
| 148 | void SyncClipCoef(); | 135 | void SyncClipCoef(); |
| @@ -193,9 +180,6 @@ private: | |||
| 193 | /// but are needed for correct emulation | 180 | /// but are needed for correct emulation |
| 194 | void CheckExtensions(); | 181 | void CheckExtensions(); |
| 195 | 182 | ||
| 196 | bool has_ARB_direct_state_access = false; | ||
| 197 | bool has_ARB_multi_bind = false; | ||
| 198 | |||
| 199 | OpenGLState state; | 183 | OpenGLState state; |
| 200 | 184 | ||
| 201 | RasterizerCacheOpenGL res_cache; | 185 | RasterizerCacheOpenGL res_cache; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp index dde2f468d..5f4cdd119 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp | |||
| @@ -405,138 +405,6 @@ void SwizzleFunc(const MortonSwizzleMode& mode, const SurfaceParams& params, | |||
| 405 | } | 405 | } |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | MICROPROFILE_DEFINE(OpenGL_BlitSurface, "OpenGL", "BlitSurface", MP_RGB(128, 192, 64)); | ||
| 409 | static bool BlitSurface(const Surface& src_surface, const Surface& dst_surface, | ||
| 410 | GLuint read_fb_handle, GLuint draw_fb_handle, GLenum src_attachment = 0, | ||
| 411 | GLenum dst_attachment = 0, std::size_t cubemap_face = 0) { | ||
| 412 | MICROPROFILE_SCOPE(OpenGL_BlitSurface); | ||
| 413 | |||
| 414 | const auto& src_params{src_surface->GetSurfaceParams()}; | ||
| 415 | const auto& dst_params{dst_surface->GetSurfaceParams()}; | ||
| 416 | |||
| 417 | OpenGLState prev_state{OpenGLState::GetCurState()}; | ||
| 418 | SCOPE_EXIT({ prev_state.Apply(); }); | ||
| 419 | |||
| 420 | OpenGLState state; | ||
| 421 | state.draw.read_framebuffer = read_fb_handle; | ||
| 422 | state.draw.draw_framebuffer = draw_fb_handle; | ||
| 423 | // Set sRGB enabled if the destination surfaces need it | ||
| 424 | state.framebuffer_srgb.enabled = dst_params.srgb_conversion; | ||
| 425 | state.ApplyFramebufferState(); | ||
| 426 | |||
| 427 | u32 buffers{}; | ||
| 428 | |||
| 429 | if (src_params.type == SurfaceType::ColorTexture) { | ||
| 430 | switch (src_params.target) { | ||
| 431 | case SurfaceTarget::Texture2D: | ||
| 432 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment, | ||
| 433 | GL_TEXTURE_2D, src_surface->Texture().handle, 0); | ||
| 434 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 435 | 0, 0); | ||
| 436 | break; | ||
| 437 | case SurfaceTarget::TextureCubemap: | ||
| 438 | glFramebufferTexture2D( | ||
| 439 | GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment, | ||
| 440 | static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), | ||
| 441 | src_surface->Texture().handle, 0); | ||
| 442 | glFramebufferTexture2D( | ||
| 443 | GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, | ||
| 444 | static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0); | ||
| 445 | break; | ||
| 446 | case SurfaceTarget::Texture2DArray: | ||
| 447 | glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment, | ||
| 448 | src_surface->Texture().handle, 0, 0); | ||
| 449 | glFramebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0); | ||
| 450 | break; | ||
| 451 | case SurfaceTarget::Texture3D: | ||
| 452 | glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment, | ||
| 453 | SurfaceTargetToGL(src_params.target), | ||
| 454 | src_surface->Texture().handle, 0, 0); | ||
| 455 | glFramebufferTexture3D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, | ||
| 456 | SurfaceTargetToGL(src_params.target), 0, 0, 0); | ||
| 457 | break; | ||
| 458 | default: | ||
| 459 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment, | ||
| 460 | GL_TEXTURE_2D, src_surface->Texture().handle, 0); | ||
| 461 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 462 | 0, 0); | ||
| 463 | break; | ||
| 464 | } | ||
| 465 | |||
| 466 | switch (dst_params.target) { | ||
| 467 | case SurfaceTarget::Texture2D: | ||
| 468 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment, | ||
| 469 | GL_TEXTURE_2D, dst_surface->Texture().handle, 0); | ||
| 470 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 471 | 0, 0); | ||
| 472 | break; | ||
| 473 | case SurfaceTarget::TextureCubemap: | ||
| 474 | glFramebufferTexture2D( | ||
| 475 | GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment, | ||
| 476 | static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), | ||
| 477 | dst_surface->Texture().handle, 0); | ||
| 478 | glFramebufferTexture2D( | ||
| 479 | GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, | ||
| 480 | static_cast<GLenum>(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubemap_face), 0, 0); | ||
| 481 | break; | ||
| 482 | case SurfaceTarget::Texture2DArray: | ||
| 483 | glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment, | ||
| 484 | dst_surface->Texture().handle, 0, 0); | ||
| 485 | glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, 0, 0, 0); | ||
| 486 | break; | ||
| 487 | |||
| 488 | case SurfaceTarget::Texture3D: | ||
| 489 | glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment, | ||
| 490 | SurfaceTargetToGL(dst_params.target), | ||
| 491 | dst_surface->Texture().handle, 0, 0); | ||
| 492 | glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, | ||
| 493 | SurfaceTargetToGL(dst_params.target), 0, 0, 0); | ||
| 494 | break; | ||
| 495 | default: | ||
| 496 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment, | ||
| 497 | GL_TEXTURE_2D, dst_surface->Texture().handle, 0); | ||
| 498 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 499 | 0, 0); | ||
| 500 | break; | ||
| 501 | } | ||
| 502 | |||
| 503 | buffers = GL_COLOR_BUFFER_BIT; | ||
| 504 | } else if (src_params.type == SurfaceType::Depth) { | ||
| 505 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment, | ||
| 506 | GL_TEXTURE_2D, 0, 0); | ||
| 507 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, | ||
| 508 | src_surface->Texture().handle, 0); | ||
| 509 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 510 | |||
| 511 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment, | ||
| 512 | GL_TEXTURE_2D, 0, 0); | ||
| 513 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, | ||
| 514 | dst_surface->Texture().handle, 0); | ||
| 515 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, 0, 0); | ||
| 516 | |||
| 517 | buffers = GL_DEPTH_BUFFER_BIT; | ||
| 518 | } else if (src_params.type == SurfaceType::DepthStencil) { | ||
| 519 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + src_attachment, | ||
| 520 | GL_TEXTURE_2D, 0, 0); | ||
| 521 | glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 522 | src_surface->Texture().handle, 0); | ||
| 523 | |||
| 524 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + dst_attachment, | ||
| 525 | GL_TEXTURE_2D, 0, 0); | ||
| 526 | glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, | ||
| 527 | dst_surface->Texture().handle, 0); | ||
| 528 | |||
| 529 | buffers = GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; | ||
| 530 | } | ||
| 531 | |||
| 532 | const auto& rect{src_params.GetRect()}; | ||
| 533 | glBlitFramebuffer(rect.left, rect.bottom, rect.right, rect.top, rect.left, rect.bottom, | ||
| 534 | rect.right, rect.top, buffers, | ||
| 535 | buffers == GL_COLOR_BUFFER_BIT ? GL_LINEAR : GL_NEAREST); | ||
| 536 | |||
| 537 | return true; | ||
| 538 | } | ||
| 539 | |||
| 540 | static void FastCopySurface(const Surface& src_surface, const Surface& dst_surface) { | 408 | static void FastCopySurface(const Surface& src_surface, const Surface& dst_surface) { |
| 541 | const auto& src_params{src_surface->GetSurfaceParams()}; | 409 | const auto& src_params{src_surface->GetSurfaceParams()}; |
| 542 | const auto& dst_params{dst_surface->GetSurfaceParams()}; | 410 | const auto& dst_params{dst_surface->GetSurfaceParams()}; |
| @@ -841,9 +709,10 @@ void CachedSurface::LoadGLBuffer() { | |||
| 841 | const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl}; | 709 | const auto texture_src_data_end{texture_src_data + params.size_in_bytes_gl}; |
| 842 | gl_buffer[0].assign(texture_src_data, texture_src_data_end); | 710 | gl_buffer[0].assign(texture_src_data, texture_src_data_end); |
| 843 | } | 711 | } |
| 844 | for (u32 i = 0; i < params.max_mip_level; i++) | 712 | for (u32 i = 0; i < params.max_mip_level; i++) { |
| 845 | ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), | 713 | ConvertFormatAsNeeded_LoadGLBuffer(gl_buffer[i], params.pixel_format, params.MipWidth(i), |
| 846 | params.MipHeight(i), params.MipDepth(i)); | 714 | params.MipHeight(i), params.MipDepth(i)); |
| 715 | } | ||
| 847 | } | 716 | } |
| 848 | 717 | ||
| 849 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); | 718 | MICROPROFILE_DEFINE(OpenGL_SurfaceFlush, "OpenGL", "Surface Flush", MP_RGB(128, 192, 64)); |
| @@ -1163,7 +1032,10 @@ void RasterizerCacheOpenGL::AccurateCopySurface(const Surface& src_surface, | |||
| 1163 | const Surface& dst_surface) { | 1032 | const Surface& dst_surface) { |
| 1164 | const auto& src_params{src_surface->GetSurfaceParams()}; | 1033 | const auto& src_params{src_surface->GetSurfaceParams()}; |
| 1165 | const auto& dst_params{dst_surface->GetSurfaceParams()}; | 1034 | const auto& dst_params{dst_surface->GetSurfaceParams()}; |
| 1166 | FlushRegion(src_params.addr, dst_params.MemorySize()); | 1035 | |
| 1036 | // Flush enough memory for both the source and destination surface | ||
| 1037 | FlushRegion(src_params.addr, std::max(src_params.MemorySize(), dst_params.MemorySize())); | ||
| 1038 | |||
| 1167 | LoadSurface(dst_surface); | 1039 | LoadSurface(dst_surface); |
| 1168 | } | 1040 | } |
| 1169 | 1041 | ||
| @@ -1189,20 +1061,9 @@ Surface RasterizerCacheOpenGL::RecreateSurface(const Surface& old_surface, | |||
| 1189 | return new_surface; | 1061 | return new_surface; |
| 1190 | } | 1062 | } |
| 1191 | 1063 | ||
| 1192 | // If the format is the same, just do a framebuffer blit. This is significantly faster than | ||
| 1193 | // using PBOs. The is also likely less accurate, as textures will be converted rather than | ||
| 1194 | // reinterpreted. When use_accurate_gpu_emulation setting is enabled, perform a more accurate | ||
| 1195 | // surface copy, where pixels are reinterpreted as a new format (without conversion). This | ||
| 1196 | // code path uses OpenGL PBOs and is quite slow. | ||
| 1197 | const bool is_blit{old_params.pixel_format == new_params.pixel_format}; | ||
| 1198 | |||
| 1199 | switch (new_params.target) { | 1064 | switch (new_params.target) { |
| 1200 | case SurfaceTarget::Texture2D: | 1065 | case SurfaceTarget::Texture2D: |
| 1201 | if (is_blit) { | 1066 | CopySurface(old_surface, new_surface, copy_pbo.handle); |
| 1202 | BlitSurface(old_surface, new_surface, read_framebuffer.handle, draw_framebuffer.handle); | ||
| 1203 | } else { | ||
| 1204 | CopySurface(old_surface, new_surface, copy_pbo.handle); | ||
| 1205 | } | ||
| 1206 | break; | 1067 | break; |
| 1207 | case SurfaceTarget::Texture3D: | 1068 | case SurfaceTarget::Texture3D: |
| 1208 | AccurateCopySurface(old_surface, new_surface); | 1069 | AccurateCopySurface(old_surface, new_surface); |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 0c4524d5c..8d68156bf 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -201,14 +201,53 @@ private: | |||
| 201 | } | 201 | } |
| 202 | }; | 202 | }; |
| 203 | 203 | ||
| 204 | template <typename T> | ||
| 205 | class ShaderScopedScope { | ||
| 206 | public: | ||
| 207 | explicit ShaderScopedScope(T& writer, std::string_view begin_expr, std::string end_expr) | ||
| 208 | : writer(writer), end_expr(std::move(end_expr)) { | ||
| 209 | |||
| 210 | if (begin_expr.empty()) { | ||
| 211 | writer.AddLine('{'); | ||
| 212 | } else { | ||
| 213 | writer.AddExpression(begin_expr); | ||
| 214 | writer.AddLine(" {"); | ||
| 215 | } | ||
| 216 | ++writer.scope; | ||
| 217 | } | ||
| 218 | |||
| 219 | ShaderScopedScope(const ShaderScopedScope&) = delete; | ||
| 220 | |||
| 221 | ~ShaderScopedScope() { | ||
| 222 | --writer.scope; | ||
| 223 | if (end_expr.empty()) { | ||
| 224 | writer.AddLine('}'); | ||
| 225 | } else { | ||
| 226 | writer.AddExpression("} "); | ||
| 227 | writer.AddExpression(end_expr); | ||
| 228 | writer.AddLine(';'); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 232 | ShaderScopedScope& operator=(const ShaderScopedScope&) = delete; | ||
| 233 | |||
| 234 | private: | ||
| 235 | T& writer; | ||
| 236 | std::string end_expr; | ||
| 237 | }; | ||
| 238 | |||
| 204 | class ShaderWriter { | 239 | class ShaderWriter { |
| 205 | public: | 240 | public: |
| 206 | void AddLine(std::string_view text) { | 241 | void AddExpression(std::string_view text) { |
| 207 | DEBUG_ASSERT(scope >= 0); | 242 | DEBUG_ASSERT(scope >= 0); |
| 208 | if (!text.empty()) { | 243 | if (!text.empty()) { |
| 209 | AppendIndentation(); | 244 | AppendIndentation(); |
| 210 | } | 245 | } |
| 211 | shader_source += text; | 246 | shader_source += text; |
| 247 | } | ||
| 248 | |||
| 249 | void AddLine(std::string_view text) { | ||
| 250 | AddExpression(text); | ||
| 212 | AddNewLine(); | 251 | AddNewLine(); |
| 213 | } | 252 | } |
| 214 | 253 | ||
| @@ -228,6 +267,11 @@ public: | |||
| 228 | return std::move(shader_source); | 267 | return std::move(shader_source); |
| 229 | } | 268 | } |
| 230 | 269 | ||
| 270 | ShaderScopedScope<ShaderWriter> Scope(std::string_view begin_expr = {}, | ||
| 271 | std::string end_expr = {}) { | ||
| 272 | return ShaderScopedScope(*this, begin_expr, end_expr); | ||
| 273 | } | ||
| 274 | |||
| 231 | int scope = 0; | 275 | int scope = 0; |
| 232 | 276 | ||
| 233 | private: | 277 | private: |
| @@ -311,7 +355,7 @@ public: | |||
| 311 | // Default - do nothing | 355 | // Default - do nothing |
| 312 | return value; | 356 | return value; |
| 313 | default: | 357 | default: |
| 314 | UNIMPLEMENTED_MSG("Unimplemented conversion size: {}", static_cast<u32>(size)); | 358 | UNREACHABLE_MSG("Unimplemented conversion size: {}", static_cast<u32>(size)); |
| 315 | } | 359 | } |
| 316 | } | 360 | } |
| 317 | 361 | ||
| @@ -525,6 +569,7 @@ public: | |||
| 525 | ((header.vtg.clip_distances >> index) & 1) == 0, | 569 | ((header.vtg.clip_distances >> index) & 1) == 0, |
| 526 | "Shader is setting gl_ClipDistance{} without enabling it in the header", index); | 570 | "Shader is setting gl_ClipDistance{} without enabling it in the header", index); |
| 527 | 571 | ||
| 572 | clip_distances[index] = true; | ||
| 528 | fixed_pipeline_output_attributes_used.insert(attribute); | 573 | fixed_pipeline_output_attributes_used.insert(attribute); |
| 529 | shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';'); | 574 | shader.AddLine(dest + '[' + std::to_string(index) + "] = " + src + ';'); |
| 530 | break; | 575 | break; |
| @@ -602,6 +647,11 @@ public: | |||
| 602 | return used_samplers; | 647 | return used_samplers; |
| 603 | } | 648 | } |
| 604 | 649 | ||
| 650 | /// Returns an array of the used clip distances. | ||
| 651 | const std::array<bool, Maxwell::NumClipDistances>& GetClipDistances() const { | ||
| 652 | return clip_distances; | ||
| 653 | } | ||
| 654 | |||
| 605 | /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if | 655 | /// Returns the GLSL sampler used for the input shader sampler, and creates a new one if |
| 606 | /// necessary. | 656 | /// necessary. |
| 607 | std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, | 657 | std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type, |
| @@ -810,14 +860,12 @@ private: | |||
| 810 | } | 860 | } |
| 811 | 861 | ||
| 812 | if (precise && stage != Maxwell3D::Regs::ShaderStage::Fragment) { | 862 | if (precise && stage != Maxwell3D::Regs::ShaderStage::Fragment) { |
| 813 | shader.AddLine('{'); | 863 | const auto scope = shader.Scope(); |
| 814 | ++shader.scope; | 864 | |
| 815 | // This avoids optimizations of constant propagation and keeps the code as the original | 865 | // This avoids optimizations of constant propagation and keeps the code as the original |
| 816 | // Sadly using the precise keyword causes "linking" errors on fragment shaders. | 866 | // Sadly using the precise keyword causes "linking" errors on fragment shaders. |
| 817 | shader.AddLine("precise float tmp = " + src + ';'); | 867 | shader.AddLine("precise float tmp = " + src + ';'); |
| 818 | shader.AddLine(dest + " = tmp;"); | 868 | shader.AddLine(dest + " = tmp;"); |
| 819 | --shader.scope; | ||
| 820 | shader.AddLine('}'); | ||
| 821 | } else { | 869 | } else { |
| 822 | shader.AddLine(dest + " = " + src + ';'); | 870 | shader.AddLine(dest + " = " + src + ';'); |
| 823 | } | 871 | } |
| @@ -975,6 +1023,7 @@ private: | |||
| 975 | const std::string& suffix; | 1023 | const std::string& suffix; |
| 976 | const Tegra::Shader::Header& header; | 1024 | const Tegra::Shader::Header& header; |
| 977 | std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used; | 1025 | std::unordered_set<Attribute::Index> fixed_pipeline_output_attributes_used; |
| 1026 | std::array<bool, Maxwell::NumClipDistances> clip_distances{}; | ||
| 978 | u64 local_memory_size; | 1027 | u64 local_memory_size; |
| 979 | }; | 1028 | }; |
| 980 | 1029 | ||
| @@ -997,7 +1046,8 @@ public: | |||
| 997 | 1046 | ||
| 998 | /// Returns entries in the shader that are useful for external functions | 1047 | /// Returns entries in the shader that are useful for external functions |
| 999 | ShaderEntries GetEntries() const { | 1048 | ShaderEntries GetEntries() const { |
| 1000 | return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), shader_length}; | 1049 | return {regs.GetConstBuffersDeclarations(), regs.GetSamplers(), regs.GetClipDistances(), |
| 1050 | shader_length}; | ||
| 1001 | } | 1051 | } |
| 1002 | 1052 | ||
| 1003 | private: | 1053 | private: |
| @@ -1293,15 +1343,7 @@ private: | |||
| 1293 | regs.SetRegisterToInteger(dest, true, 0, result, 1, 1); | 1343 | regs.SetRegisterToInteger(dest, true, 0, result, 1, 1); |
| 1294 | } | 1344 | } |
| 1295 | 1345 | ||
| 1296 | void WriteTexsInstruction(const Instruction& instr, const std::string& coord, | 1346 | void WriteTexsInstruction(const Instruction& instr, const std::string& texture) { |
| 1297 | const std::string& texture) { | ||
| 1298 | // Add an extra scope and declare the texture coords inside to prevent | ||
| 1299 | // overwriting them in case they are used as outputs of the texs instruction. | ||
| 1300 | shader.AddLine('{'); | ||
| 1301 | ++shader.scope; | ||
| 1302 | shader.AddLine(coord); | ||
| 1303 | shader.AddLine("vec4 texture_tmp = " + texture + ';'); | ||
| 1304 | |||
| 1305 | // TEXS has two destination registers and a swizzle. The first two elements in the swizzle | 1347 | // TEXS has two destination registers and a swizzle. The first two elements in the swizzle |
| 1306 | // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1 | 1348 | // go into gpr0+0 and gpr0+1, and the rest goes into gpr28+0 and gpr28+1 |
| 1307 | 1349 | ||
| @@ -1313,19 +1355,17 @@ private: | |||
| 1313 | 1355 | ||
| 1314 | if (written_components < 2) { | 1356 | if (written_components < 2) { |
| 1315 | // Write the first two swizzle components to gpr0 and gpr0+1 | 1357 | // Write the first two swizzle components to gpr0 and gpr0+1 |
| 1316 | regs.SetRegisterToFloat(instr.gpr0, component, "texture_tmp", 1, 4, false, | 1358 | regs.SetRegisterToFloat(instr.gpr0, component, texture, 1, 4, false, |
| 1317 | written_components % 2); | 1359 | written_components % 2); |
| 1318 | } else { | 1360 | } else { |
| 1319 | ASSERT(instr.texs.HasTwoDestinations()); | 1361 | ASSERT(instr.texs.HasTwoDestinations()); |
| 1320 | // Write the rest of the swizzle components to gpr28 and gpr28+1 | 1362 | // Write the rest of the swizzle components to gpr28 and gpr28+1 |
| 1321 | regs.SetRegisterToFloat(instr.gpr28, component, "texture_tmp", 1, 4, false, | 1363 | regs.SetRegisterToFloat(instr.gpr28, component, texture, 1, 4, false, |
| 1322 | written_components % 2); | 1364 | written_components % 2); |
| 1323 | } | 1365 | } |
| 1324 | 1366 | ||
| 1325 | ++written_components; | 1367 | ++written_components; |
| 1326 | } | 1368 | } |
| 1327 | --shader.scope; | ||
| 1328 | shader.AddLine('}'); | ||
| 1329 | } | 1369 | } |
| 1330 | 1370 | ||
| 1331 | static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) { | 1371 | static u32 TextureCoordinates(Tegra::Shader::TextureType texture_type) { |
| @@ -1348,12 +1388,10 @@ private: | |||
| 1348 | * top. | 1388 | * top. |
| 1349 | */ | 1389 | */ |
| 1350 | void EmitPushToFlowStack(u32 target) { | 1390 | void EmitPushToFlowStack(u32 target) { |
| 1351 | shader.AddLine('{'); | 1391 | const auto scope = shader.Scope(); |
| 1352 | ++shader.scope; | 1392 | |
| 1353 | shader.AddLine("flow_stack[flow_stack_top] = " + std::to_string(target) + "u;"); | 1393 | shader.AddLine("flow_stack[flow_stack_top] = " + std::to_string(target) + "u;"); |
| 1354 | shader.AddLine("flow_stack_top++;"); | 1394 | shader.AddLine("flow_stack_top++;"); |
| 1355 | --shader.scope; | ||
| 1356 | shader.AddLine('}'); | ||
| 1357 | } | 1395 | } |
| 1358 | 1396 | ||
| 1359 | /* | 1397 | /* |
| @@ -1361,13 +1399,11 @@ private: | |||
| 1361 | * popped address and decrementing the stack top. | 1399 | * popped address and decrementing the stack top. |
| 1362 | */ | 1400 | */ |
| 1363 | void EmitPopFromFlowStack() { | 1401 | void EmitPopFromFlowStack() { |
| 1364 | shader.AddLine('{'); | 1402 | const auto scope = shader.Scope(); |
| 1365 | ++shader.scope; | 1403 | |
| 1366 | shader.AddLine("flow_stack_top--;"); | 1404 | shader.AddLine("flow_stack_top--;"); |
| 1367 | shader.AddLine("jmp_to = flow_stack[flow_stack_top];"); | 1405 | shader.AddLine("jmp_to = flow_stack[flow_stack_top];"); |
| 1368 | shader.AddLine("break;"); | 1406 | shader.AddLine("break;"); |
| 1369 | --shader.scope; | ||
| 1370 | shader.AddLine('}'); | ||
| 1371 | } | 1407 | } |
| 1372 | 1408 | ||
| 1373 | /// Writes the output values from a fragment shader to the corresponding GLSL output variables. | 1409 | /// Writes the output values from a fragment shader to the corresponding GLSL output variables. |
| @@ -1479,6 +1515,161 @@ private: | |||
| 1479 | } | 1515 | } |
| 1480 | } | 1516 | } |
| 1481 | 1517 | ||
| 1518 | std::pair<size_t, std::string> ValidateAndGetCoordinateElement( | ||
| 1519 | const Tegra::Shader::TextureType texture_type, const bool depth_compare, | ||
| 1520 | const bool is_array, const bool lod_bias_enabled, size_t max_coords, size_t max_inputs) { | ||
| 1521 | const size_t coord_count = TextureCoordinates(texture_type); | ||
| 1522 | |||
| 1523 | size_t total_coord_count = coord_count + (is_array ? 1 : 0) + (depth_compare ? 1 : 0); | ||
| 1524 | const size_t total_reg_count = total_coord_count + (lod_bias_enabled ? 1 : 0); | ||
| 1525 | if (total_coord_count > max_coords || total_reg_count > max_inputs) { | ||
| 1526 | UNIMPLEMENTED_MSG("Unsupported Texture operation"); | ||
| 1527 | total_coord_count = std::min(total_coord_count, max_coords); | ||
| 1528 | } | ||
| 1529 | // 1D.DC opengl is using a vec3 but 2nd component is ignored later. | ||
| 1530 | total_coord_count += | ||
| 1531 | (depth_compare && !is_array && texture_type == Tegra::Shader::TextureType::Texture1D) | ||
| 1532 | ? 1 | ||
| 1533 | : 0; | ||
| 1534 | |||
| 1535 | constexpr std::array<const char*, 5> coord_container{ | ||
| 1536 | {"", "float coord = (", "vec2 coord = vec2(", "vec3 coord = vec3(", | ||
| 1537 | "vec4 coord = vec4("}}; | ||
| 1538 | |||
| 1539 | return std::pair<size_t, std::string>(coord_count, coord_container[total_coord_count]); | ||
| 1540 | } | ||
| 1541 | |||
| 1542 | std::string GetTextureCode(const Tegra::Shader::Instruction& instr, | ||
| 1543 | const Tegra::Shader::TextureType texture_type, | ||
| 1544 | const Tegra::Shader::TextureProcessMode process_mode, | ||
| 1545 | const bool depth_compare, const bool is_array, | ||
| 1546 | const size_t bias_offset) { | ||
| 1547 | |||
| 1548 | if ((texture_type == Tegra::Shader::TextureType::Texture3D && | ||
| 1549 | (is_array || depth_compare)) || | ||
| 1550 | (texture_type == Tegra::Shader::TextureType::TextureCube && is_array && | ||
| 1551 | depth_compare)) { | ||
| 1552 | UNIMPLEMENTED_MSG("This method is not supported."); | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | const std::string sampler = | ||
| 1556 | GetSampler(instr.sampler, texture_type, is_array, depth_compare); | ||
| 1557 | |||
| 1558 | const bool lod_needed = process_mode == Tegra::Shader::TextureProcessMode::LZ || | ||
| 1559 | process_mode == Tegra::Shader::TextureProcessMode::LL || | ||
| 1560 | process_mode == Tegra::Shader::TextureProcessMode::LLA; | ||
| 1561 | |||
| 1562 | const bool gl_lod_supported = !( | ||
| 1563 | (texture_type == Tegra::Shader::TextureType::Texture2D && is_array && depth_compare) || | ||
| 1564 | (texture_type == Tegra::Shader::TextureType::TextureCube && !is_array && | ||
| 1565 | depth_compare)); | ||
| 1566 | |||
| 1567 | const std::string read_method = lod_needed && gl_lod_supported ? "textureLod(" : "texture("; | ||
| 1568 | std::string texture = read_method + sampler + ", coord"; | ||
| 1569 | |||
| 1570 | if (process_mode != Tegra::Shader::TextureProcessMode::None) { | ||
| 1571 | if (process_mode == Tegra::Shader::TextureProcessMode::LZ) { | ||
| 1572 | if (gl_lod_supported) { | ||
| 1573 | texture += ", 0"; | ||
| 1574 | } else { | ||
| 1575 | // Lod 0 is emulated by a big negative bias | ||
| 1576 | // in scenarios that are not supported by glsl | ||
| 1577 | texture += ", -1000"; | ||
| 1578 | } | ||
| 1579 | } else { | ||
| 1580 | // If present, lod or bias are always stored in the register indexed by the | ||
| 1581 | // gpr20 | ||
| 1582 | // field with an offset depending on the usage of the other registers | ||
| 1583 | texture += ',' + regs.GetRegisterAsFloat(instr.gpr20.Value() + bias_offset); | ||
| 1584 | } | ||
| 1585 | } | ||
| 1586 | texture += ")"; | ||
| 1587 | return texture; | ||
| 1588 | } | ||
| 1589 | |||
| 1590 | std::pair<std::string, std::string> GetTEXCode( | ||
| 1591 | const Instruction& instr, const Tegra::Shader::TextureType texture_type, | ||
| 1592 | const Tegra::Shader::TextureProcessMode process_mode, const bool depth_compare, | ||
| 1593 | const bool is_array) { | ||
| 1594 | const bool lod_bias_enabled = (process_mode != Tegra::Shader::TextureProcessMode::None && | ||
| 1595 | process_mode != Tegra::Shader::TextureProcessMode::LZ); | ||
| 1596 | |||
| 1597 | const auto [coord_count, coord_dcl] = ValidateAndGetCoordinateElement( | ||
| 1598 | texture_type, depth_compare, is_array, lod_bias_enabled, 4, 5); | ||
| 1599 | // If enabled arrays index is always stored in the gpr8 field | ||
| 1600 | const u64 array_register = instr.gpr8.Value(); | ||
| 1601 | // First coordinate index is the gpr8 or gpr8 + 1 when arrays are used | ||
| 1602 | const u64 coord_register = array_register + (is_array ? 1 : 0); | ||
| 1603 | |||
| 1604 | std::string coord = coord_dcl; | ||
| 1605 | for (size_t i = 0; i < coord_count;) { | ||
| 1606 | coord += regs.GetRegisterAsFloat(coord_register + i); | ||
| 1607 | ++i; | ||
| 1608 | if (i != coord_count) { | ||
| 1609 | coord += ','; | ||
| 1610 | } | ||
| 1611 | } | ||
| 1612 | // 1D.DC in opengl the 2nd component is ignored. | ||
| 1613 | if (depth_compare && !is_array && texture_type == Tegra::Shader::TextureType::Texture1D) { | ||
| 1614 | coord += ",0.0"; | ||
| 1615 | } | ||
| 1616 | if (depth_compare) { | ||
| 1617 | // Depth is always stored in the register signaled by gpr20 | ||
| 1618 | // or in the next register if lod or bias are used | ||
| 1619 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); | ||
| 1620 | coord += ',' + regs.GetRegisterAsFloat(depth_register); | ||
| 1621 | } | ||
| 1622 | if (is_array) { | ||
| 1623 | coord += ',' + regs.GetRegisterAsInteger(array_register); | ||
| 1624 | } | ||
| 1625 | coord += ");"; | ||
| 1626 | return std::make_pair( | ||
| 1627 | coord, GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, 0)); | ||
| 1628 | } | ||
| 1629 | |||
| 1630 | std::pair<std::string, std::string> GetTEXSCode( | ||
| 1631 | const Instruction& instr, const Tegra::Shader::TextureType texture_type, | ||
| 1632 | const Tegra::Shader::TextureProcessMode process_mode, const bool depth_compare, | ||
| 1633 | const bool is_array) { | ||
| 1634 | const bool lod_bias_enabled = (process_mode != Tegra::Shader::TextureProcessMode::None && | ||
| 1635 | process_mode != Tegra::Shader::TextureProcessMode::LZ); | ||
| 1636 | |||
| 1637 | const auto [coord_count, coord_dcl] = ValidateAndGetCoordinateElement( | ||
| 1638 | texture_type, depth_compare, is_array, lod_bias_enabled, 4, 4); | ||
| 1639 | // If enabled arrays index is always stored in the gpr8 field | ||
| 1640 | const u64 array_register = instr.gpr8.Value(); | ||
| 1641 | // First coordinate index is stored in gpr8 field or (gpr8 + 1) when arrays are used | ||
| 1642 | const u64 coord_register = array_register + (is_array ? 1 : 0); | ||
| 1643 | const u64 last_coord_register = | ||
| 1644 | (is_array || !(lod_bias_enabled || depth_compare) || (coord_count > 2)) | ||
| 1645 | ? static_cast<u64>(instr.gpr20.Value()) | ||
| 1646 | : coord_register + 1; | ||
| 1647 | |||
| 1648 | std::string coord = coord_dcl; | ||
| 1649 | for (size_t i = 0; i < coord_count; ++i) { | ||
| 1650 | const bool last = (i == (coord_count - 1)) && (coord_count > 1); | ||
| 1651 | coord += regs.GetRegisterAsFloat(last ? last_coord_register : coord_register + i); | ||
| 1652 | if (!last) { | ||
| 1653 | coord += ','; | ||
| 1654 | } | ||
| 1655 | } | ||
| 1656 | |||
| 1657 | if (depth_compare) { | ||
| 1658 | // Depth is always stored in the register signaled by gpr20 | ||
| 1659 | // or in the next register if lod or bias are used | ||
| 1660 | const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0); | ||
| 1661 | coord += ',' + regs.GetRegisterAsFloat(depth_register); | ||
| 1662 | } | ||
| 1663 | if (is_array) { | ||
| 1664 | coord += ',' + regs.GetRegisterAsInteger(array_register); | ||
| 1665 | } | ||
| 1666 | coord += ");"; | ||
| 1667 | |||
| 1668 | return std::make_pair(coord, | ||
| 1669 | GetTextureCode(instr, texture_type, process_mode, depth_compare, | ||
| 1670 | is_array, (coord_count > 2 ? 1 : 0))); | ||
| 1671 | } | ||
| 1672 | |||
| 1482 | /** | 1673 | /** |
| 1483 | * Compiles a single instruction from Tegra to GLSL. | 1674 | * Compiles a single instruction from Tegra to GLSL. |
| 1484 | * @param offset the offset of the Tegra shader instruction. | 1675 | * @param offset the offset of the Tegra shader instruction. |
| @@ -2279,8 +2470,7 @@ private: | |||
| 2279 | UNIMPLEMENTED_IF(instr.conversion.selector); | 2470 | UNIMPLEMENTED_IF(instr.conversion.selector); |
| 2280 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, | 2471 | UNIMPLEMENTED_IF_MSG(instr.generates_cc, |
| 2281 | "Condition codes generation in I2F is not implemented"); | 2472 | "Condition codes generation in I2F is not implemented"); |
| 2282 | 2473 | std::string op_a; | |
| 2283 | std::string op_a{}; | ||
| 2284 | 2474 | ||
| 2285 | if (instr.is_b_gpr) { | 2475 | if (instr.is_b_gpr) { |
| 2286 | op_a = | 2476 | op_a = |
| @@ -2436,10 +2626,7 @@ private: | |||
| 2436 | case OpCode::Id::LD_C: { | 2626 | case OpCode::Id::LD_C: { |
| 2437 | UNIMPLEMENTED_IF(instr.ld_c.unknown != 0); | 2627 | UNIMPLEMENTED_IF(instr.ld_c.unknown != 0); |
| 2438 | 2628 | ||
| 2439 | // Add an extra scope and declare the index register inside to prevent | 2629 | const auto scope = shader.Scope(); |
| 2440 | // overwriting it in case it is used as an output of the LD instruction. | ||
| 2441 | shader.AddLine("{"); | ||
| 2442 | ++shader.scope; | ||
| 2443 | 2630 | ||
| 2444 | shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + | 2631 | shader.AddLine("uint index = (" + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + |
| 2445 | " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);"); | 2632 | " / 4) & (MAX_CONSTBUFFER_ELEMENTS - 1);"); |
| @@ -2465,19 +2652,13 @@ private: | |||
| 2465 | UNIMPLEMENTED_MSG("Unhandled type: {}", | 2652 | UNIMPLEMENTED_MSG("Unhandled type: {}", |
| 2466 | static_cast<unsigned>(instr.ld_c.type.Value())); | 2653 | static_cast<unsigned>(instr.ld_c.type.Value())); |
| 2467 | } | 2654 | } |
| 2468 | |||
| 2469 | --shader.scope; | ||
| 2470 | shader.AddLine("}"); | ||
| 2471 | break; | 2655 | break; |
| 2472 | } | 2656 | } |
| 2473 | case OpCode::Id::LD_L: { | 2657 | case OpCode::Id::LD_L: { |
| 2474 | UNIMPLEMENTED_IF_MSG(instr.ld_l.unknown == 1, "LD_L Unhandled mode: {}", | 2658 | UNIMPLEMENTED_IF_MSG(instr.ld_l.unknown == 1, "LD_L Unhandled mode: {}", |
| 2475 | static_cast<unsigned>(instr.ld_l.unknown.Value())); | 2659 | static_cast<unsigned>(instr.ld_l.unknown.Value())); |
| 2476 | 2660 | ||
| 2477 | // Add an extra scope and declare the index register inside to prevent | 2661 | const auto scope = shader.Scope(); |
| 2478 | // overwriting it in case it is used as an output of the LD instruction. | ||
| 2479 | shader.AddLine('{'); | ||
| 2480 | ++shader.scope; | ||
| 2481 | 2662 | ||
| 2482 | std::string op = '(' + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + " + " + | 2663 | std::string op = '(' + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + " + " + |
| 2483 | std::to_string(instr.smem_imm.Value()) + ')'; | 2664 | std::to_string(instr.smem_imm.Value()) + ')'; |
| @@ -2494,9 +2675,6 @@ private: | |||
| 2494 | UNIMPLEMENTED_MSG("LD_L Unhandled type: {}", | 2675 | UNIMPLEMENTED_MSG("LD_L Unhandled type: {}", |
| 2495 | static_cast<unsigned>(instr.ldst_sl.type.Value())); | 2676 | static_cast<unsigned>(instr.ldst_sl.type.Value())); |
| 2496 | } | 2677 | } |
| 2497 | |||
| 2498 | --shader.scope; | ||
| 2499 | shader.AddLine('}'); | ||
| 2500 | break; | 2678 | break; |
| 2501 | } | 2679 | } |
| 2502 | case OpCode::Id::ST_A: { | 2680 | case OpCode::Id::ST_A: { |
| @@ -2531,10 +2709,7 @@ private: | |||
| 2531 | UNIMPLEMENTED_IF_MSG(instr.st_l.unknown == 0, "ST_L Unhandled mode: {}", | 2709 | UNIMPLEMENTED_IF_MSG(instr.st_l.unknown == 0, "ST_L Unhandled mode: {}", |
| 2532 | static_cast<unsigned>(instr.st_l.unknown.Value())); | 2710 | static_cast<unsigned>(instr.st_l.unknown.Value())); |
| 2533 | 2711 | ||
| 2534 | // Add an extra scope and declare the index register inside to prevent | 2712 | const auto scope = shader.Scope(); |
| 2535 | // overwriting it in case it is used as an output of the LD instruction. | ||
| 2536 | shader.AddLine('{'); | ||
| 2537 | ++shader.scope; | ||
| 2538 | 2713 | ||
| 2539 | std::string op = '(' + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + " + " + | 2714 | std::string op = '(' + regs.GetRegisterAsInteger(instr.gpr8, 0, false) + " + " + |
| 2540 | std::to_string(instr.smem_imm.Value()) + ')'; | 2715 | std::to_string(instr.smem_imm.Value()) + ')'; |
| @@ -2549,179 +2724,28 @@ private: | |||
| 2549 | UNIMPLEMENTED_MSG("ST_L Unhandled type: {}", | 2724 | UNIMPLEMENTED_MSG("ST_L Unhandled type: {}", |
| 2550 | static_cast<unsigned>(instr.ldst_sl.type.Value())); | 2725 | static_cast<unsigned>(instr.ldst_sl.type.Value())); |
| 2551 | } | 2726 | } |
| 2552 | |||
| 2553 | --shader.scope; | ||
| 2554 | shader.AddLine('}'); | ||
| 2555 | break; | 2727 | break; |
| 2556 | } | 2728 | } |
| 2557 | case OpCode::Id::TEX: { | 2729 | case OpCode::Id::TEX: { |
| 2558 | Tegra::Shader::TextureType texture_type{instr.tex.texture_type}; | 2730 | Tegra::Shader::TextureType texture_type{instr.tex.texture_type}; |
| 2559 | std::string coord; | ||
| 2560 | const bool is_array = instr.tex.array != 0; | 2731 | const bool is_array = instr.tex.array != 0; |
| 2561 | 2732 | const bool depth_compare = | |
| 2733 | instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | ||
| 2734 | const auto process_mode = instr.tex.GetTextureProcessMode(); | ||
| 2562 | UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2735 | UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2563 | "NODEP is not implemented"); | 2736 | "NODEP is not implemented"); |
| 2564 | UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | 2737 | UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), |
| 2565 | "AOFFI is not implemented"); | 2738 | "AOFFI is not implemented"); |
| 2566 | 2739 | ||
| 2567 | const bool depth_compare = | 2740 | const auto [coord, texture] = |
| 2568 | instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | 2741 | GetTEXCode(instr, texture_type, process_mode, depth_compare, is_array); |
| 2569 | u32 num_coordinates = TextureCoordinates(texture_type); | ||
| 2570 | u32 start_index = 0; | ||
| 2571 | std::string array_elem; | ||
| 2572 | if (is_array) { | ||
| 2573 | array_elem = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 2574 | start_index = 1; | ||
| 2575 | } | ||
| 2576 | const auto process_mode = instr.tex.GetTextureProcessMode(); | ||
| 2577 | u32 start_index_b = 0; | ||
| 2578 | std::string lod_value; | ||
| 2579 | if (process_mode != Tegra::Shader::TextureProcessMode::LZ && | ||
| 2580 | process_mode != Tegra::Shader::TextureProcessMode::None) { | ||
| 2581 | start_index_b = 1; | ||
| 2582 | lod_value = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2583 | } | ||
| 2584 | |||
| 2585 | std::string depth_value; | ||
| 2586 | if (depth_compare) { | ||
| 2587 | depth_value = regs.GetRegisterAsFloat(instr.gpr20.Value() + start_index_b); | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | bool depth_compare_extra = false; | ||
| 2591 | |||
| 2592 | switch (num_coordinates) { | ||
| 2593 | case 1: { | ||
| 2594 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index); | ||
| 2595 | if (is_array) { | ||
| 2596 | if (depth_compare) { | ||
| 2597 | coord = "vec3 coords = vec3(" + x + ", " + depth_value + ", " + | ||
| 2598 | array_elem + ");"; | ||
| 2599 | } else { | ||
| 2600 | coord = "vec2 coords = vec2(" + x + ", " + array_elem + ");"; | ||
| 2601 | } | ||
| 2602 | } else { | ||
| 2603 | if (depth_compare) { | ||
| 2604 | coord = "vec2 coords = vec2(" + x + ", " + depth_value + ");"; | ||
| 2605 | } else { | ||
| 2606 | coord = "float coords = " + x + ';'; | ||
| 2607 | } | ||
| 2608 | } | ||
| 2609 | break; | ||
| 2610 | } | ||
| 2611 | case 2: { | ||
| 2612 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index); | ||
| 2613 | const std::string y = | ||
| 2614 | regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 1); | ||
| 2615 | if (is_array) { | ||
| 2616 | if (depth_compare) { | ||
| 2617 | coord = "vec4 coords = vec4(" + x + ", " + y + ", " + depth_value + | ||
| 2618 | ", " + array_elem + ");"; | ||
| 2619 | } else { | ||
| 2620 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + array_elem + ");"; | ||
| 2621 | } | ||
| 2622 | } else { | ||
| 2623 | if (depth_compare) { | ||
| 2624 | coord = | ||
| 2625 | "vec3 coords = vec3(" + x + ", " + y + ", " + depth_value + ");"; | ||
| 2626 | } else { | ||
| 2627 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 2628 | } | ||
| 2629 | } | ||
| 2630 | break; | ||
| 2631 | } | ||
| 2632 | case 3: { | ||
| 2633 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index); | ||
| 2634 | const std::string y = | ||
| 2635 | regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 1); | ||
| 2636 | const std::string z = | ||
| 2637 | regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 2); | ||
| 2638 | if (is_array) { | ||
| 2639 | depth_compare_extra = depth_compare; | ||
| 2640 | coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + | ||
| 2641 | array_elem + ");"; | ||
| 2642 | } else { | ||
| 2643 | if (depth_compare) { | ||
| 2644 | coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + | ||
| 2645 | depth_value + ");"; | ||
| 2646 | } else { | ||
| 2647 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 2648 | } | ||
| 2649 | } | ||
| 2650 | break; | ||
| 2651 | } | ||
| 2652 | default: | ||
| 2653 | UNIMPLEMENTED_MSG("Unhandled coordinates number {}", | ||
| 2654 | static_cast<u32>(num_coordinates)); | ||
| 2655 | |||
| 2656 | // Fallback to interpreting as a 2D texture for now | ||
| 2657 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 2658 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 2659 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 2660 | texture_type = Tegra::Shader::TextureType::Texture2D; | ||
| 2661 | } | ||
| 2662 | |||
| 2663 | const std::string sampler = | ||
| 2664 | GetSampler(instr.sampler, texture_type, is_array, depth_compare); | ||
| 2665 | // Add an extra scope and declare the texture coords inside to prevent | ||
| 2666 | // overwriting them in case they are used as outputs of the texs instruction. | ||
| 2667 | 2742 | ||
| 2668 | shader.AddLine('{'); | 2743 | const auto scope = shader.Scope(); |
| 2669 | ++shader.scope; | ||
| 2670 | shader.AddLine(coord); | 2744 | shader.AddLine(coord); |
| 2671 | std::string texture; | ||
| 2672 | 2745 | ||
| 2673 | switch (instr.tex.GetTextureProcessMode()) { | 2746 | if (depth_compare) { |
| 2674 | case Tegra::Shader::TextureProcessMode::None: { | 2747 | regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); |
| 2675 | if (!depth_compare_extra) { | 2748 | } else { |
| 2676 | texture = "texture(" + sampler + ", coords)"; | ||
| 2677 | } else { | ||
| 2678 | texture = "texture(" + sampler + ", coords, " + depth_value + ')'; | ||
| 2679 | } | ||
| 2680 | break; | ||
| 2681 | } | ||
| 2682 | case Tegra::Shader::TextureProcessMode::LZ: { | ||
| 2683 | if (!depth_compare_extra) { | ||
| 2684 | texture = "textureLod(" + sampler + ", coords, 0.0)"; | ||
| 2685 | } else { | ||
| 2686 | texture = "texture(" + sampler + ", coords, " + depth_value + ')'; | ||
| 2687 | } | ||
| 2688 | break; | ||
| 2689 | } | ||
| 2690 | case Tegra::Shader::TextureProcessMode::LB: | ||
| 2691 | case Tegra::Shader::TextureProcessMode::LBA: { | ||
| 2692 | // TODO: Figure if A suffix changes the equation at all. | ||
| 2693 | if (!depth_compare_extra) { | ||
| 2694 | texture = "texture(" + sampler + ", coords, " + lod_value + ')'; | ||
| 2695 | } else { | ||
| 2696 | texture = "texture(" + sampler + ", coords, " + depth_value + ')'; | ||
| 2697 | LOG_WARNING(HW_GPU, | ||
| 2698 | "OpenGL Limitation: can't set bias value along depth compare"); | ||
| 2699 | } | ||
| 2700 | break; | ||
| 2701 | } | ||
| 2702 | case Tegra::Shader::TextureProcessMode::LL: | ||
| 2703 | case Tegra::Shader::TextureProcessMode::LLA: { | ||
| 2704 | // TODO: Figure if A suffix changes the equation at all. | ||
| 2705 | if (!depth_compare_extra) { | ||
| 2706 | texture = "textureLod(" + sampler + ", coords, " + lod_value + ')'; | ||
| 2707 | } else { | ||
| 2708 | texture = "texture(" + sampler + ", coords, " + depth_value + ')'; | ||
| 2709 | LOG_WARNING(HW_GPU, | ||
| 2710 | "OpenGL Limitation: can't set lod value along depth compare"); | ||
| 2711 | } | ||
| 2712 | break; | ||
| 2713 | } | ||
| 2714 | default: { | ||
| 2715 | if (!depth_compare_extra) { | ||
| 2716 | texture = "texture(" + sampler + ", coords)"; | ||
| 2717 | } else { | ||
| 2718 | texture = "texture(" + sampler + ", coords, " + depth_value + ')'; | ||
| 2719 | } | ||
| 2720 | UNIMPLEMENTED_MSG("Unhandled texture process mode {}", | ||
| 2721 | static_cast<u32>(instr.tex.GetTextureProcessMode())); | ||
| 2722 | } | ||
| 2723 | } | ||
| 2724 | if (!depth_compare) { | ||
| 2725 | shader.AddLine("vec4 texture_tmp = " + texture + ';'); | 2749 | shader.AddLine("vec4 texture_tmp = " + texture + ';'); |
| 2726 | std::size_t dest_elem{}; | 2750 | std::size_t dest_elem{}; |
| 2727 | for (std::size_t elem = 0; elem < 4; ++elem) { | 2751 | for (std::size_t elem = 0; elem < 4; ++elem) { |
| @@ -2733,138 +2757,33 @@ private: | |||
| 2733 | dest_elem); | 2757 | dest_elem); |
| 2734 | ++dest_elem; | 2758 | ++dest_elem; |
| 2735 | } | 2759 | } |
| 2736 | } else { | ||
| 2737 | regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); | ||
| 2738 | } | 2760 | } |
| 2739 | --shader.scope; | ||
| 2740 | shader.AddLine('}'); | ||
| 2741 | break; | 2761 | break; |
| 2742 | } | 2762 | } |
| 2743 | case OpCode::Id::TEXS: { | 2763 | case OpCode::Id::TEXS: { |
| 2744 | Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; | 2764 | Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()}; |
| 2745 | bool is_array{instr.texs.IsArrayTexture()}; | 2765 | const bool is_array{instr.texs.IsArrayTexture()}; |
| 2746 | |||
| 2747 | UNIMPLEMENTED_IF_MSG(instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | ||
| 2748 | "NODEP is not implemented"); | ||
| 2749 | |||
| 2750 | const bool depth_compare = | 2766 | const bool depth_compare = |
| 2751 | instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | 2767 | instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); |
| 2752 | u32 num_coordinates = TextureCoordinates(texture_type); | ||
| 2753 | const auto process_mode = instr.texs.GetTextureProcessMode(); | 2768 | const auto process_mode = instr.texs.GetTextureProcessMode(); |
| 2754 | std::string lod_value; | 2769 | UNIMPLEMENTED_IF_MSG(instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2755 | std::string coord; | 2770 | "NODEP is not implemented"); |
| 2756 | u32 lod_offset = 0; | ||
| 2757 | if (process_mode == Tegra::Shader::TextureProcessMode::LL) { | ||
| 2758 | if (num_coordinates > 2) { | ||
| 2759 | lod_value = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); | ||
| 2760 | lod_offset = 2; | ||
| 2761 | } else { | ||
| 2762 | lod_value = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2763 | lod_offset = 1; | ||
| 2764 | } | ||
| 2765 | } | ||
| 2766 | 2771 | ||
| 2767 | switch (num_coordinates) { | 2772 | const auto scope = shader.Scope(); |
| 2768 | case 1: { | 2773 | |
| 2769 | coord = "float coords = " + regs.GetRegisterAsFloat(instr.gpr8) + ';'; | 2774 | const auto [coord, texture] = |
| 2770 | break; | 2775 | GetTEXSCode(instr, texture_type, process_mode, depth_compare, is_array); |
| 2771 | } | 2776 | |
| 2772 | case 2: { | 2777 | shader.AddLine(coord); |
| 2773 | if (is_array) { | ||
| 2774 | if (depth_compare) { | ||
| 2775 | const std::string index = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 2776 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 2777 | const std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2778 | const std::string z = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1); | ||
| 2779 | coord = "vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " + index + | ||
| 2780 | ");"; | ||
| 2781 | } else { | ||
| 2782 | const std::string index = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 2783 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 2784 | const std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2785 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");"; | ||
| 2786 | } | ||
| 2787 | } else { | ||
| 2788 | if (lod_offset != 0) { | ||
| 2789 | if (depth_compare) { | ||
| 2790 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 2791 | const std::string y = | ||
| 2792 | regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 2793 | const std::string z = | ||
| 2794 | regs.GetRegisterAsFloat(instr.gpr20.Value() + lod_offset); | ||
| 2795 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 2796 | } else { | ||
| 2797 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 2798 | const std::string y = | ||
| 2799 | regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 2800 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 2801 | } | ||
| 2802 | } else { | ||
| 2803 | if (depth_compare) { | ||
| 2804 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 2805 | const std::string y = | ||
| 2806 | regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 2807 | const std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2808 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 2809 | } else { | ||
| 2810 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 2811 | const std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2812 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 2813 | } | ||
| 2814 | } | ||
| 2815 | } | ||
| 2816 | break; | ||
| 2817 | } | ||
| 2818 | case 3: { | ||
| 2819 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 2820 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | ||
| 2821 | const std::string z = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2822 | coord = "vec3 coords = vec3(" + x + ", " + y + ", " + z + ");"; | ||
| 2823 | break; | ||
| 2824 | } | ||
| 2825 | default: | ||
| 2826 | UNIMPLEMENTED_MSG("Unhandled coordinates number {}", | ||
| 2827 | static_cast<u32>(num_coordinates)); | ||
| 2828 | 2778 | ||
| 2829 | // Fallback to interpreting as a 2D texture for now | ||
| 2830 | const std::string x = regs.GetRegisterAsFloat(instr.gpr8); | ||
| 2831 | const std::string y = regs.GetRegisterAsFloat(instr.gpr20); | ||
| 2832 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | ||
| 2833 | texture_type = Tegra::Shader::TextureType::Texture2D; | ||
| 2834 | is_array = false; | ||
| 2835 | } | ||
| 2836 | const std::string sampler = | ||
| 2837 | GetSampler(instr.sampler, texture_type, is_array, depth_compare); | ||
| 2838 | std::string texture; | ||
| 2839 | switch (process_mode) { | ||
| 2840 | case Tegra::Shader::TextureProcessMode::None: { | ||
| 2841 | texture = "texture(" + sampler + ", coords)"; | ||
| 2842 | break; | ||
| 2843 | } | ||
| 2844 | case Tegra::Shader::TextureProcessMode::LZ: { | ||
| 2845 | if (depth_compare && is_array) { | ||
| 2846 | texture = "texture(" + sampler + ", coords)"; | ||
| 2847 | } else { | ||
| 2848 | texture = "textureLod(" + sampler + ", coords, 0.0)"; | ||
| 2849 | } | ||
| 2850 | break; | ||
| 2851 | } | ||
| 2852 | case Tegra::Shader::TextureProcessMode::LL: { | ||
| 2853 | texture = "textureLod(" + sampler + ", coords, " + lod_value + ')'; | ||
| 2854 | break; | ||
| 2855 | } | ||
| 2856 | default: { | ||
| 2857 | texture = "texture(" + sampler + ", coords)"; | ||
| 2858 | UNIMPLEMENTED_MSG("Unhandled texture process mode {}", | ||
| 2859 | static_cast<u32>(instr.texs.GetTextureProcessMode())); | ||
| 2860 | } | ||
| 2861 | } | ||
| 2862 | if (!depth_compare) { | 2779 | if (!depth_compare) { |
| 2863 | WriteTexsInstruction(instr, coord, texture); | 2780 | shader.AddLine("vec4 texture_tmp = " + texture + ';'); |
| 2781 | |||
| 2864 | } else { | 2782 | } else { |
| 2865 | WriteTexsInstruction(instr, coord, "vec4(" + texture + ')'); | 2783 | shader.AddLine("vec4 texture_tmp = vec4(" + texture + ");"); |
| 2866 | } | 2784 | } |
| 2867 | 2785 | ||
| 2786 | WriteTexsInstruction(instr, "texture_tmp"); | ||
| 2868 | break; | 2787 | break; |
| 2869 | } | 2788 | } |
| 2870 | case OpCode::Id::TLDS: { | 2789 | case OpCode::Id::TLDS: { |
| @@ -2883,15 +2802,12 @@ private: | |||
| 2883 | 2802 | ||
| 2884 | u32 extra_op_offset = 0; | 2803 | u32 extra_op_offset = 0; |
| 2885 | 2804 | ||
| 2886 | // Scope to avoid variable name overlaps. | 2805 | ShaderScopedScope scope = shader.Scope(); |
| 2887 | shader.AddLine('{'); | ||
| 2888 | ++shader.scope; | ||
| 2889 | std::string coords; | ||
| 2890 | 2806 | ||
| 2891 | switch (texture_type) { | 2807 | switch (texture_type) { |
| 2892 | case Tegra::Shader::TextureType::Texture1D: { | 2808 | case Tegra::Shader::TextureType::Texture1D: { |
| 2893 | const std::string x = regs.GetRegisterAsInteger(instr.gpr8); | 2809 | const std::string x = regs.GetRegisterAsInteger(instr.gpr8); |
| 2894 | coords = "float coords = " + x + ';'; | 2810 | shader.AddLine("float coords = " + x + ';'); |
| 2895 | break; | 2811 | break; |
| 2896 | } | 2812 | } |
| 2897 | case Tegra::Shader::TextureType::Texture2D: { | 2813 | case Tegra::Shader::TextureType::Texture2D: { |
| @@ -2900,7 +2816,7 @@ private: | |||
| 2900 | const std::string x = regs.GetRegisterAsInteger(instr.gpr8); | 2816 | const std::string x = regs.GetRegisterAsInteger(instr.gpr8); |
| 2901 | const std::string y = regs.GetRegisterAsInteger(instr.gpr20); | 2817 | const std::string y = regs.GetRegisterAsInteger(instr.gpr20); |
| 2902 | // shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");"); | 2818 | // shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");"); |
| 2903 | coords = "ivec2 coords = ivec2(" + x + ", " + y + ");"; | 2819 | shader.AddLine("ivec2 coords = ivec2(" + x + ", " + y + ");"); |
| 2904 | extra_op_offset = 1; | 2820 | extra_op_offset = 1; |
| 2905 | break; | 2821 | break; |
| 2906 | } | 2822 | } |
| @@ -2909,35 +2825,29 @@ private: | |||
| 2909 | } | 2825 | } |
| 2910 | const std::string sampler = | 2826 | const std::string sampler = |
| 2911 | GetSampler(instr.sampler, texture_type, is_array, false); | 2827 | GetSampler(instr.sampler, texture_type, is_array, false); |
| 2912 | std::string texture = "texelFetch(" + sampler + ", coords, 0)"; | ||
| 2913 | switch (instr.tlds.GetTextureProcessMode()) { | ||
| 2914 | case Tegra::Shader::TextureProcessMode::LZ: { | ||
| 2915 | texture = "texelFetch(" + sampler + ", coords, 0)"; | ||
| 2916 | break; | ||
| 2917 | } | ||
| 2918 | case Tegra::Shader::TextureProcessMode::LL: { | ||
| 2919 | shader.AddLine( | ||
| 2920 | "float lod = " + | ||
| 2921 | regs.GetRegisterAsInteger(instr.gpr20.Value() + extra_op_offset) + ';'); | ||
| 2922 | texture = "texelFetch(" + sampler + ", coords, lod)"; | ||
| 2923 | break; | ||
| 2924 | } | ||
| 2925 | default: { | ||
| 2926 | texture = "texelFetch(" + sampler + ", coords, 0)"; | ||
| 2927 | UNIMPLEMENTED_MSG("Unhandled texture process mode {}", | ||
| 2928 | static_cast<u32>(instr.tlds.GetTextureProcessMode())); | ||
| 2929 | } | ||
| 2930 | } | ||
| 2931 | WriteTexsInstruction(instr, coords, texture); | ||
| 2932 | 2828 | ||
| 2933 | --shader.scope; | 2829 | const std::string texture = [&]() { |
| 2934 | shader.AddLine('}'); | 2830 | switch (instr.tlds.GetTextureProcessMode()) { |
| 2831 | case Tegra::Shader::TextureProcessMode::LZ: | ||
| 2832 | return "texelFetch(" + sampler + ", coords, 0)"; | ||
| 2833 | case Tegra::Shader::TextureProcessMode::LL: | ||
| 2834 | shader.AddLine( | ||
| 2835 | "float lod = " + | ||
| 2836 | regs.GetRegisterAsInteger(instr.gpr20.Value() + extra_op_offset) + ';'); | ||
| 2837 | return "texelFetch(" + sampler + ", coords, lod)"; | ||
| 2838 | default: | ||
| 2839 | UNIMPLEMENTED_MSG("Unhandled texture process mode {}", | ||
| 2840 | static_cast<u32>(instr.tlds.GetTextureProcessMode())); | ||
| 2841 | return "texelFetch(" + sampler + ", coords, 0)"; | ||
| 2842 | } | ||
| 2843 | }(); | ||
| 2844 | |||
| 2845 | WriteTexsInstruction(instr, texture); | ||
| 2935 | break; | 2846 | break; |
| 2936 | } | 2847 | } |
| 2937 | case OpCode::Id::TLD4: { | 2848 | case OpCode::Id::TLD4: { |
| 2938 | ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D); | 2849 | ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D); |
| 2939 | ASSERT(instr.tld4.array == 0); | 2850 | ASSERT(instr.tld4.array == 0); |
| 2940 | std::string coord; | ||
| 2941 | 2851 | ||
| 2942 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2852 | UNIMPLEMENTED_IF_MSG(instr.tld4.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 2943 | "NODEP is not implemented"); | 2853 | "NODEP is not implemented"); |
| @@ -2954,10 +2864,7 @@ private: | |||
| 2954 | if (depth_compare) | 2864 | if (depth_compare) |
| 2955 | num_coordinates += 1; | 2865 | num_coordinates += 1; |
| 2956 | 2866 | ||
| 2957 | // Add an extra scope and declare the texture coords inside to prevent | 2867 | const auto scope = shader.Scope(); |
| 2958 | // overwriting them in case they are used as outputs of the texs instruction. | ||
| 2959 | shader.AddLine('{'); | ||
| 2960 | ++shader.scope; | ||
| 2961 | 2868 | ||
| 2962 | switch (num_coordinates) { | 2869 | switch (num_coordinates) { |
| 2963 | case 2: { | 2870 | case 2: { |
| @@ -2988,23 +2895,19 @@ private: | |||
| 2988 | const std::string texture = "textureGather(" + sampler + ", coords, " + | 2895 | const std::string texture = "textureGather(" + sampler + ", coords, " + |
| 2989 | std::to_string(instr.tld4.component) + ')'; | 2896 | std::to_string(instr.tld4.component) + ')'; |
| 2990 | 2897 | ||
| 2991 | if (!depth_compare) { | 2898 | if (depth_compare) { |
| 2992 | shader.AddLine("vec4 texture_tmp = " + texture + ';'); | 2899 | regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); |
| 2900 | } else { | ||
| 2993 | std::size_t dest_elem{}; | 2901 | std::size_t dest_elem{}; |
| 2994 | for (std::size_t elem = 0; elem < 4; ++elem) { | 2902 | for (std::size_t elem = 0; elem < 4; ++elem) { |
| 2995 | if (!instr.tex.IsComponentEnabled(elem)) { | 2903 | if (!instr.tex.IsComponentEnabled(elem)) { |
| 2996 | // Skip disabled components | 2904 | // Skip disabled components |
| 2997 | continue; | 2905 | continue; |
| 2998 | } | 2906 | } |
| 2999 | regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false, | 2907 | regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem); |
| 3000 | dest_elem); | ||
| 3001 | ++dest_elem; | 2908 | ++dest_elem; |
| 3002 | } | 2909 | } |
| 3003 | } else { | ||
| 3004 | regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false); | ||
| 3005 | } | 2910 | } |
| 3006 | --shader.scope; | ||
| 3007 | shader.AddLine('}'); | ||
| 3008 | break; | 2911 | break; |
| 3009 | } | 2912 | } |
| 3010 | case OpCode::Id::TLD4S: { | 2913 | case OpCode::Id::TLD4S: { |
| @@ -3015,10 +2918,7 @@ private: | |||
| 3015 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), | 2918 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI), |
| 3016 | "AOFFI is not implemented"); | 2919 | "AOFFI is not implemented"); |
| 3017 | 2920 | ||
| 3018 | // Scope to avoid variable name overlaps. | 2921 | const auto scope = shader.Scope(); |
| 3019 | shader.AddLine('{'); | ||
| 3020 | ++shader.scope; | ||
| 3021 | std::string coords; | ||
| 3022 | 2922 | ||
| 3023 | const bool depth_compare = | 2923 | const bool depth_compare = |
| 3024 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); | 2924 | instr.tld4s.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC); |
| @@ -3027,33 +2927,29 @@ private: | |||
| 3027 | // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. | 2927 | // TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction. |
| 3028 | const std::string sampler = GetSampler( | 2928 | const std::string sampler = GetSampler( |
| 3029 | instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare); | 2929 | instr.sampler, Tegra::Shader::TextureType::Texture2D, false, depth_compare); |
| 3030 | if (!depth_compare) { | 2930 | if (depth_compare) { |
| 3031 | coords = "vec2 coords = vec2(" + op_a + ", " + op_b + ");"; | ||
| 3032 | } else { | ||
| 3033 | // Note: TLD4S coordinate encoding works just like TEXS's | 2931 | // Note: TLD4S coordinate encoding works just like TEXS's |
| 3034 | const std::string op_y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 2932 | const std::string op_y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 3035 | coords = "vec3 coords = vec3(" + op_a + ", " + op_y + ", " + op_b + ");"; | 2933 | shader.AddLine("vec3 coords = vec3(" + op_a + ", " + op_y + ", " + op_b + ");"); |
| 3036 | } | ||
| 3037 | const std::string texture = "textureGather(" + sampler + ", coords, " + | ||
| 3038 | std::to_string(instr.tld4s.component) + ')'; | ||
| 3039 | |||
| 3040 | if (!depth_compare) { | ||
| 3041 | WriteTexsInstruction(instr, coords, texture); | ||
| 3042 | } else { | 2934 | } else { |
| 3043 | WriteTexsInstruction(instr, coords, "vec4(" + texture + ')'); | 2935 | shader.AddLine("vec2 coords = vec2(" + op_a + ", " + op_b + ");"); |
| 3044 | } | 2936 | } |
| 3045 | 2937 | ||
| 3046 | --shader.scope; | 2938 | std::string texture = "textureGather(" + sampler + ", coords, " + |
| 3047 | shader.AddLine('}'); | 2939 | std::to_string(instr.tld4s.component) + ')'; |
| 2940 | if (depth_compare) { | ||
| 2941 | texture = "vec4(" + texture + ')'; | ||
| 2942 | } | ||
| 2943 | WriteTexsInstruction(instr, texture); | ||
| 3048 | break; | 2944 | break; |
| 3049 | } | 2945 | } |
| 3050 | case OpCode::Id::TXQ: { | 2946 | case OpCode::Id::TXQ: { |
| 3051 | UNIMPLEMENTED_IF_MSG(instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), | 2947 | UNIMPLEMENTED_IF_MSG(instr.txq.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP), |
| 3052 | "NODEP is not implemented"); | 2948 | "NODEP is not implemented"); |
| 3053 | 2949 | ||
| 3054 | ++shader.scope; | 2950 | const auto scope = shader.Scope(); |
| 3055 | shader.AddLine('{'); | 2951 | |
| 3056 | // TODO: the new commits on the texture refactor, change the way samplers work. | 2952 | // TODO: The new commits on the texture refactor, change the way samplers work. |
| 3057 | // Sadly, not all texture instructions specify the type of texture their sampler | 2953 | // Sadly, not all texture instructions specify the type of texture their sampler |
| 3058 | // uses. This must be fixed at a later instance. | 2954 | // uses. This must be fixed at a later instance. |
| 3059 | const std::string sampler = | 2955 | const std::string sampler = |
| @@ -3064,7 +2960,8 @@ private: | |||
| 3064 | regs.GetRegisterAsInteger(instr.gpr8) + ')'; | 2960 | regs.GetRegisterAsInteger(instr.gpr8) + ')'; |
| 3065 | const std::string mip_level = "textureQueryLevels(" + sampler + ')'; | 2961 | const std::string mip_level = "textureQueryLevels(" + sampler + ')'; |
| 3066 | shader.AddLine("ivec2 sizes = " + texture + ';'); | 2962 | shader.AddLine("ivec2 sizes = " + texture + ';'); |
| 3067 | regs.SetRegisterToInteger(instr.gpr0, true, 0, "sizes.x", 1, 1); | 2963 | |
| 2964 | regs.SetRegisterToInteger(instr.gpr0.Value() + 0, true, 0, "sizes.x", 1, 1); | ||
| 3068 | regs.SetRegisterToInteger(instr.gpr0.Value() + 1, true, 0, "sizes.y", 1, 1); | 2965 | regs.SetRegisterToInteger(instr.gpr0.Value() + 1, true, 0, "sizes.y", 1, 1); |
| 3069 | regs.SetRegisterToInteger(instr.gpr0.Value() + 2, true, 0, "0", 1, 1); | 2966 | regs.SetRegisterToInteger(instr.gpr0.Value() + 2, true, 0, "0", 1, 1); |
| 3070 | regs.SetRegisterToInteger(instr.gpr0.Value() + 3, true, 0, mip_level, 1, 1); | 2967 | regs.SetRegisterToInteger(instr.gpr0.Value() + 3, true, 0, mip_level, 1, 1); |
| @@ -3075,8 +2972,6 @@ private: | |||
| 3075 | static_cast<u32>(instr.txq.query_type.Value())); | 2972 | static_cast<u32>(instr.txq.query_type.Value())); |
| 3076 | } | 2973 | } |
| 3077 | } | 2974 | } |
| 3078 | --shader.scope; | ||
| 3079 | shader.AddLine('}'); | ||
| 3080 | break; | 2975 | break; |
| 3081 | } | 2976 | } |
| 3082 | case OpCode::Id::TMML: { | 2977 | case OpCode::Id::TMML: { |
| @@ -3091,17 +2986,18 @@ private: | |||
| 3091 | const std::string sampler = | 2986 | const std::string sampler = |
| 3092 | GetSampler(instr.sampler, texture_type, is_array, false); | 2987 | GetSampler(instr.sampler, texture_type, is_array, false); |
| 3093 | 2988 | ||
| 3094 | // TODO: add coordinates for different samplers once other texture types are | 2989 | const auto scope = shader.Scope(); |
| 2990 | |||
| 2991 | // TODO: Add coordinates for different samplers once other texture types are | ||
| 3095 | // implemented. | 2992 | // implemented. |
| 3096 | std::string coord; | ||
| 3097 | switch (texture_type) { | 2993 | switch (texture_type) { |
| 3098 | case Tegra::Shader::TextureType::Texture1D: { | 2994 | case Tegra::Shader::TextureType::Texture1D: { |
| 3099 | coord = "float coords = " + x + ';'; | 2995 | shader.AddLine("float coords = " + x + ';'); |
| 3100 | break; | 2996 | break; |
| 3101 | } | 2997 | } |
| 3102 | case Tegra::Shader::TextureType::Texture2D: { | 2998 | case Tegra::Shader::TextureType::Texture2D: { |
| 3103 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 2999 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 3104 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 3000 | shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");"); |
| 3105 | break; | 3001 | break; |
| 3106 | } | 3002 | } |
| 3107 | default: | 3003 | default: |
| @@ -3109,22 +3005,15 @@ private: | |||
| 3109 | 3005 | ||
| 3110 | // Fallback to interpreting as a 2D texture for now | 3006 | // Fallback to interpreting as a 2D texture for now |
| 3111 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); | 3007 | const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1); |
| 3112 | coord = "vec2 coords = vec2(" + x + ", " + y + ");"; | 3008 | shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");"); |
| 3113 | texture_type = Tegra::Shader::TextureType::Texture2D; | 3009 | texture_type = Tegra::Shader::TextureType::Texture2D; |
| 3114 | } | 3010 | } |
| 3115 | // Add an extra scope and declare the texture coords inside to prevent | 3011 | |
| 3116 | // overwriting them in case they are used as outputs of the texs instruction. | ||
| 3117 | shader.AddLine('{'); | ||
| 3118 | ++shader.scope; | ||
| 3119 | shader.AddLine(coord); | ||
| 3120 | const std::string texture = "textureQueryLod(" + sampler + ", coords)"; | 3012 | const std::string texture = "textureQueryLod(" + sampler + ", coords)"; |
| 3121 | const std::string tmp = "vec2 tmp = " + texture + "*vec2(256.0, 256.0);"; | 3013 | shader.AddLine("vec2 tmp = " + texture + " * vec2(256.0, 256.0);"); |
| 3122 | shader.AddLine(tmp); | ||
| 3123 | 3014 | ||
| 3124 | regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(tmp.y)", 1, 1); | 3015 | regs.SetRegisterToInteger(instr.gpr0, true, 0, "int(tmp.y)", 1, 1); |
| 3125 | regs.SetRegisterToInteger(instr.gpr0.Value() + 1, false, 0, "uint(tmp.x)", 1, 1); | 3016 | regs.SetRegisterToInteger(instr.gpr0.Value() + 1, false, 0, "uint(tmp.x)", 1, 1); |
| 3126 | --shader.scope; | ||
| 3127 | shader.AddLine('}'); | ||
| 3128 | break; | 3017 | break; |
| 3129 | } | 3018 | } |
| 3130 | default: { | 3019 | default: { |
| @@ -3963,4 +3852,4 @@ std::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code, u | |||
| 3963 | return {}; | 3852 | return {}; |
| 3964 | } | 3853 | } |
| 3965 | 3854 | ||
| 3966 | } // namespace OpenGL::GLShader::Decompiler | 3855 | } // namespace OpenGL::GLShader::Decompiler \ No newline at end of file |
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.h b/src/video_core/renderer_opengl/gl_shader_gen.h index b425d98ae..4fa6d7612 100644 --- a/src/video_core/renderer_opengl/gl_shader_gen.h +++ b/src/video_core/renderer_opengl/gl_shader_gen.h | |||
| @@ -163,6 +163,7 @@ private: | |||
| 163 | struct ShaderEntries { | 163 | struct ShaderEntries { |
| 164 | std::vector<ConstBufferEntry> const_buffer_entries; | 164 | std::vector<ConstBufferEntry> const_buffer_entries; |
| 165 | std::vector<SamplerEntry> texture_samplers; | 165 | std::vector<SamplerEntry> texture_samplers; |
| 166 | std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> clip_distances; | ||
| 166 | std::size_t shader_length; | 167 | std::size_t shader_length; |
| 167 | }; | 168 | }; |
| 168 | 169 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_manager.h b/src/video_core/renderer_opengl/gl_shader_manager.h index b757f5f44..4970aafed 100644 --- a/src/video_core/renderer_opengl/gl_shader_manager.h +++ b/src/video_core/renderer_opengl/gl_shader_manager.h | |||
| @@ -60,6 +60,17 @@ public: | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | void ApplyTo(OpenGLState& state) { | 62 | void ApplyTo(OpenGLState& state) { |
| 63 | UpdatePipeline(); | ||
| 64 | state.draw.shader_program = 0; | ||
| 65 | state.draw.program_pipeline = pipeline.handle; | ||
| 66 | state.geometry_shaders.enabled = (gs != 0); | ||
| 67 | } | ||
| 68 | |||
| 69 | private: | ||
| 70 | void UpdatePipeline() { | ||
| 71 | // Avoid updating the pipeline when values have no changed | ||
| 72 | if (old_vs == vs && old_fs == fs && old_gs == gs) | ||
| 73 | return; | ||
| 63 | // Workaround for AMD bug | 74 | // Workaround for AMD bug |
| 64 | glUseProgramStages(pipeline.handle, | 75 | glUseProgramStages(pipeline.handle, |
| 65 | GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, | 76 | GL_VERTEX_SHADER_BIT | GL_GEOMETRY_SHADER_BIT | GL_FRAGMENT_SHADER_BIT, |
| @@ -68,14 +79,16 @@ public: | |||
| 68 | glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, vs); | 79 | glUseProgramStages(pipeline.handle, GL_VERTEX_SHADER_BIT, vs); |
| 69 | glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, gs); | 80 | glUseProgramStages(pipeline.handle, GL_GEOMETRY_SHADER_BIT, gs); |
| 70 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs); | 81 | glUseProgramStages(pipeline.handle, GL_FRAGMENT_SHADER_BIT, fs); |
| 71 | state.draw.shader_program = 0; | 82 | |
| 72 | state.draw.program_pipeline = pipeline.handle; | 83 | // Update the old values |
| 73 | state.geometry_shaders.enabled = (gs != 0); | 84 | old_vs = vs; |
| 85 | old_fs = fs; | ||
| 86 | old_gs = gs; | ||
| 74 | } | 87 | } |
| 75 | 88 | ||
| 76 | private: | ||
| 77 | OGLPipeline pipeline; | 89 | OGLPipeline pipeline; |
| 78 | GLuint vs{}, fs{}, gs{}; | 90 | GLuint vs{}, fs{}, gs{}; |
| 91 | GLuint old_vs{}, old_fs{}, old_gs{}; | ||
| 79 | }; | 92 | }; |
| 80 | 93 | ||
| 81 | } // namespace OpenGL::GLShader | 94 | } // namespace OpenGL::GLShader |
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h index 207f9dfb3..8771421c0 100644 --- a/src/yuzu/configuration/configure_audio.h +++ b/src/yuzu/configuration/configure_audio.h | |||
| @@ -16,15 +16,14 @@ class ConfigureAudio : public QWidget { | |||
| 16 | 16 | ||
| 17 | public: | 17 | public: |
| 18 | explicit ConfigureAudio(QWidget* parent = nullptr); | 18 | explicit ConfigureAudio(QWidget* parent = nullptr); |
| 19 | ~ConfigureAudio(); | 19 | ~ConfigureAudio() override; |
| 20 | 20 | ||
| 21 | void applyConfiguration(); | 21 | void applyConfiguration(); |
| 22 | void retranslateUi(); | 22 | void retranslateUi(); |
| 23 | 23 | ||
| 24 | public slots: | 24 | private: |
| 25 | void updateAudioDevices(int sink_index); | 25 | void updateAudioDevices(int sink_index); |
| 26 | 26 | ||
| 27 | private: | ||
| 28 | void setConfiguration(); | 27 | void setConfiguration(); |
| 29 | void setOutputSinkFromSinkID(); | 28 | void setOutputSinkFromSinkID(); |
| 30 | void setAudioDeviceFromDeviceID(); | 29 | void setAudioDeviceFromDeviceID(); |
diff --git a/src/yuzu/configuration/configure_debug.h b/src/yuzu/configuration/configure_debug.h index d167eb996..c6420b18c 100644 --- a/src/yuzu/configuration/configure_debug.h +++ b/src/yuzu/configuration/configure_debug.h | |||
| @@ -16,13 +16,12 @@ class ConfigureDebug : public QWidget { | |||
| 16 | 16 | ||
| 17 | public: | 17 | public: |
| 18 | explicit ConfigureDebug(QWidget* parent = nullptr); | 18 | explicit ConfigureDebug(QWidget* parent = nullptr); |
| 19 | ~ConfigureDebug(); | 19 | ~ConfigureDebug() override; |
| 20 | 20 | ||
| 21 | void applyConfiguration(); | 21 | void applyConfiguration(); |
| 22 | 22 | ||
| 23 | private: | 23 | private: |
| 24 | void setConfiguration(); | 24 | void setConfiguration(); |
| 25 | 25 | ||
| 26 | private: | ||
| 27 | std::unique_ptr<Ui::ConfigureDebug> ui; | 26 | std::unique_ptr<Ui::ConfigureDebug> ui; |
| 28 | }; | 27 | }; |
diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index bbbdacc29..f6df7b827 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h | |||
| @@ -18,13 +18,12 @@ class ConfigureDialog : public QDialog { | |||
| 18 | 18 | ||
| 19 | public: | 19 | public: |
| 20 | explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry); | 20 | explicit ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry); |
| 21 | ~ConfigureDialog(); | 21 | ~ConfigureDialog() override; |
| 22 | 22 | ||
| 23 | void applyConfiguration(); | 23 | void applyConfiguration(); |
| 24 | 24 | ||
| 25 | private: | 25 | private: |
| 26 | void setConfiguration(); | 26 | void setConfiguration(); |
| 27 | 27 | ||
| 28 | private: | ||
| 29 | std::unique_ptr<Ui::ConfigureDialog> ui; | 28 | std::unique_ptr<Ui::ConfigureDialog> ui; |
| 30 | }; | 29 | }; |
diff --git a/src/yuzu/configuration/configure_gamelist.h b/src/yuzu/configuration/configure_gamelist.h index bbf7e25f1..bf3f1cdfa 100644 --- a/src/yuzu/configuration/configure_gamelist.h +++ b/src/yuzu/configuration/configure_gamelist.h | |||
| @@ -16,7 +16,7 @@ class ConfigureGameList : public QWidget { | |||
| 16 | 16 | ||
| 17 | public: | 17 | public: |
| 18 | explicit ConfigureGameList(QWidget* parent = nullptr); | 18 | explicit ConfigureGameList(QWidget* parent = nullptr); |
| 19 | ~ConfigureGameList(); | 19 | ~ConfigureGameList() override; |
| 20 | 20 | ||
| 21 | void applyConfiguration(); | 21 | void applyConfiguration(); |
| 22 | 22 | ||
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index 4770034cc..59738af40 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h | |||
| @@ -18,7 +18,7 @@ class ConfigureGeneral : public QWidget { | |||
| 18 | 18 | ||
| 19 | public: | 19 | public: |
| 20 | explicit ConfigureGeneral(QWidget* parent = nullptr); | 20 | explicit ConfigureGeneral(QWidget* parent = nullptr); |
| 21 | ~ConfigureGeneral(); | 21 | ~ConfigureGeneral() override; |
| 22 | 22 | ||
| 23 | void PopulateHotkeyList(const HotkeyRegistry& registry); | 23 | void PopulateHotkeyList(const HotkeyRegistry& registry); |
| 24 | void applyConfiguration(); | 24 | void applyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 9bda26fd6..d6ffc6fde 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h | |||
| @@ -16,14 +16,13 @@ class ConfigureGraphics : public QWidget { | |||
| 16 | 16 | ||
| 17 | public: | 17 | public: |
| 18 | explicit ConfigureGraphics(QWidget* parent = nullptr); | 18 | explicit ConfigureGraphics(QWidget* parent = nullptr); |
| 19 | ~ConfigureGraphics(); | 19 | ~ConfigureGraphics() override; |
| 20 | 20 | ||
| 21 | void applyConfiguration(); | 21 | void applyConfiguration(); |
| 22 | 22 | ||
| 23 | private: | 23 | private: |
| 24 | void setConfiguration(); | 24 | void setConfiguration(); |
| 25 | 25 | ||
| 26 | private: | ||
| 27 | std::unique_ptr<Ui::ConfigureGraphics> ui; | 26 | std::unique_ptr<Ui::ConfigureGraphics> ui; |
| 28 | QColor bg_color; | 27 | QColor bg_color; |
| 29 | }; | 28 | }; |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 0527d098c..830d26115 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -88,6 +88,8 @@ ConfigureInput::ConfigureInput(QWidget* parent) | |||
| 88 | [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); | 88 | [this] { CallConfigureDialog<ConfigureTouchscreenAdvanced>(*this); }); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | ConfigureInput::~ConfigureInput() = default; | ||
| 92 | |||
| 91 | void ConfigureInput::OnDockedModeChanged(bool last_state, bool new_state) { | 93 | void ConfigureInput::OnDockedModeChanged(bool last_state, bool new_state) { |
| 92 | if (ui->use_docked_mode->isChecked() && ui->handheld_connected->isChecked()) { | 94 | if (ui->use_docked_mode->isChecked() && ui->handheld_connected->isChecked()) { |
| 93 | ui->handheld_connected->setChecked(false); | 95 | ui->handheld_connected->setChecked(false); |
diff --git a/src/yuzu/configuration/configure_input.h b/src/yuzu/configuration/configure_input.h index e8723dfcb..1649e4c0b 100644 --- a/src/yuzu/configuration/configure_input.h +++ b/src/yuzu/configuration/configure_input.h | |||
| @@ -25,6 +25,7 @@ class ConfigureInput : public QWidget { | |||
| 25 | 25 | ||
| 26 | public: | 26 | public: |
| 27 | explicit ConfigureInput(QWidget* parent = nullptr); | 27 | explicit ConfigureInput(QWidget* parent = nullptr); |
| 28 | ~ConfigureInput() override; | ||
| 28 | 29 | ||
| 29 | /// Save all button configurations to settings file | 30 | /// Save all button configurations to settings file |
| 30 | void applyConfiguration(); | 31 | void applyConfiguration(); |
diff --git a/src/yuzu/configuration/configure_web.h b/src/yuzu/configuration/configure_web.h index 7741ab95d..7752ae4a1 100644 --- a/src/yuzu/configuration/configure_web.h +++ b/src/yuzu/configuration/configure_web.h | |||
| @@ -17,18 +17,17 @@ class ConfigureWeb : public QWidget { | |||
| 17 | 17 | ||
| 18 | public: | 18 | public: |
| 19 | explicit ConfigureWeb(QWidget* parent = nullptr); | 19 | explicit ConfigureWeb(QWidget* parent = nullptr); |
| 20 | ~ConfigureWeb(); | 20 | ~ConfigureWeb() override; |
| 21 | 21 | ||
| 22 | void applyConfiguration(); | 22 | void applyConfiguration(); |
| 23 | void retranslateUi(); | 23 | void retranslateUi(); |
| 24 | 24 | ||
| 25 | public slots: | 25 | private: |
| 26 | void RefreshTelemetryID(); | 26 | void RefreshTelemetryID(); |
| 27 | void OnLoginChanged(); | 27 | void OnLoginChanged(); |
| 28 | void VerifyLogin(); | 28 | void VerifyLogin(); |
| 29 | void OnLoginVerified(); | 29 | void OnLoginVerified(); |
| 30 | 30 | ||
| 31 | private: | ||
| 32 | void setConfiguration(); | 31 | void setConfiguration(); |
| 33 | 32 | ||
| 34 | bool user_verified = true; | 33 | bool user_verified = true; |
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index 0c831c9f4..f9c18ede4 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp | |||
| @@ -7,10 +7,10 @@ | |||
| 7 | 7 | ||
| 8 | #include "common/assert.h" | 8 | #include "common/assert.h" |
| 9 | #include "core/core.h" | 9 | #include "core/core.h" |
| 10 | #include "core/hle/kernel/event.h" | ||
| 11 | #include "core/hle/kernel/handle_table.h" | 10 | #include "core/hle/kernel/handle_table.h" |
| 12 | #include "core/hle/kernel/mutex.h" | 11 | #include "core/hle/kernel/mutex.h" |
| 13 | #include "core/hle/kernel/process.h" | 12 | #include "core/hle/kernel/process.h" |
| 13 | #include "core/hle/kernel/readable_event.h" | ||
| 14 | #include "core/hle/kernel/scheduler.h" | 14 | #include "core/hle/kernel/scheduler.h" |
| 15 | #include "core/hle/kernel/thread.h" | 15 | #include "core/hle/kernel/thread.h" |
| 16 | #include "core/hle/kernel/timer.h" | 16 | #include "core/hle/kernel/timer.h" |
| @@ -153,8 +153,8 @@ QString WaitTreeWaitObject::GetText() const { | |||
| 153 | 153 | ||
| 154 | std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitObject& object) { | 154 | std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitObject& object) { |
| 155 | switch (object.GetHandleType()) { | 155 | switch (object.GetHandleType()) { |
| 156 | case Kernel::HandleType::Event: | 156 | case Kernel::HandleType::ReadableEvent: |
| 157 | return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::Event&>(object)); | 157 | return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); |
| 158 | case Kernel::HandleType::Timer: | 158 | case Kernel::HandleType::Timer: |
| 159 | return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object)); | 159 | return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object)); |
| 160 | case Kernel::HandleType::Thread: | 160 | case Kernel::HandleType::Thread: |
| @@ -332,7 +332,7 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const { | |||
| 332 | return list; | 332 | return list; |
| 333 | } | 333 | } |
| 334 | 334 | ||
| 335 | WaitTreeEvent::WaitTreeEvent(const Kernel::Event& object) : WaitTreeWaitObject(object) {} | 335 | WaitTreeEvent::WaitTreeEvent(const Kernel::ReadableEvent& object) : WaitTreeWaitObject(object) {} |
| 336 | WaitTreeEvent::~WaitTreeEvent() = default; | 336 | WaitTreeEvent::~WaitTreeEvent() = default; |
| 337 | 337 | ||
| 338 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const { | 338 | std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const { |
| @@ -340,7 +340,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const { | |||
| 340 | 340 | ||
| 341 | list.push_back(std::make_unique<WaitTreeText>( | 341 | list.push_back(std::make_unique<WaitTreeText>( |
| 342 | tr("reset type = %1") | 342 | tr("reset type = %1") |
| 343 | .arg(GetResetTypeQString(static_cast<const Kernel::Event&>(object).GetResetType())))); | 343 | .arg(GetResetTypeQString( |
| 344 | static_cast<const Kernel::ReadableEvent&>(object).GetResetType())))); | ||
| 344 | return list; | 345 | return list; |
| 345 | } | 346 | } |
| 346 | 347 | ||
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h index 331f89885..492fb6ac9 100644 --- a/src/yuzu/debugger/wait_tree.h +++ b/src/yuzu/debugger/wait_tree.h | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | class EmuThread; | 17 | class EmuThread; |
| 18 | 18 | ||
| 19 | namespace Kernel { | 19 | namespace Kernel { |
| 20 | class ReadableEvent; | ||
| 20 | class WaitObject; | 21 | class WaitObject; |
| 21 | class Event; | ||
| 22 | class Thread; | 22 | class Thread; |
| 23 | class Timer; | 23 | class Timer; |
| 24 | } // namespace Kernel | 24 | } // namespace Kernel |
| @@ -144,7 +144,7 @@ public: | |||
| 144 | class WaitTreeEvent : public WaitTreeWaitObject { | 144 | class WaitTreeEvent : public WaitTreeWaitObject { |
| 145 | Q_OBJECT | 145 | Q_OBJECT |
| 146 | public: | 146 | public: |
| 147 | explicit WaitTreeEvent(const Kernel::Event& object); | 147 | explicit WaitTreeEvent(const Kernel::ReadableEvent& object); |
| 148 | ~WaitTreeEvent() override; | 148 | ~WaitTreeEvent() override; |
| 149 | 149 | ||
| 150 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; | 150 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 11a8c390b..b52a50915 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -214,6 +214,7 @@ GameList::GameList(FileSys::VirtualFilesystem vfs, GMainWindow* parent) | |||
| 214 | tree_view->setEditTriggers(QHeaderView::NoEditTriggers); | 214 | tree_view->setEditTriggers(QHeaderView::NoEditTriggers); |
| 215 | tree_view->setUniformRowHeights(true); | 215 | tree_view->setUniformRowHeights(true); |
| 216 | tree_view->setContextMenuPolicy(Qt::CustomContextMenu); | 216 | tree_view->setContextMenuPolicy(Qt::CustomContextMenu); |
| 217 | tree_view->setStyleSheet("QTreeView{ border: none; }"); | ||
| 217 | 218 | ||
| 218 | item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1); | 219 | item_model->insertColumns(0, UISettings::values.show_add_ons ? COLUMN_COUNT : COLUMN_COUNT - 1); |
| 219 | item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); | 220 | item_model->setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name")); |
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 362902e46..1edc60df7 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp | |||
| @@ -97,11 +97,11 @@ GameListWorker::~GameListWorker() = default; | |||
| 97 | 97 | ||
| 98 | void GameListWorker::AddInstalledTitlesToGameList() { | 98 | void GameListWorker::AddInstalledTitlesToGameList() { |
| 99 | const auto cache = Service::FileSystem::GetUnionContents(); | 99 | const auto cache = Service::FileSystem::GetUnionContents(); |
| 100 | const auto installed_games = cache->ListEntriesFilter(FileSys::TitleType::Application, | 100 | const auto installed_games = cache.ListEntriesFilter(FileSys::TitleType::Application, |
| 101 | FileSys::ContentRecordType::Program); | 101 | FileSys::ContentRecordType::Program); |
| 102 | 102 | ||
| 103 | for (const auto& game : installed_games) { | 103 | for (const auto& game : installed_games) { |
| 104 | const auto file = cache->GetEntryUnparsed(game); | 104 | const auto file = cache.GetEntryUnparsed(game); |
| 105 | std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(file); | 105 | std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(file); |
| 106 | if (!loader) | 106 | if (!loader) |
| 107 | continue; | 107 | continue; |
| @@ -112,7 +112,7 @@ void GameListWorker::AddInstalledTitlesToGameList() { | |||
| 112 | loader->ReadProgramId(program_id); | 112 | loader->ReadProgramId(program_id); |
| 113 | 113 | ||
| 114 | const FileSys::PatchManager patch{program_id}; | 114 | const FileSys::PatchManager patch{program_id}; |
| 115 | const auto control = cache->GetEntry(game.title_id, FileSys::ContentRecordType::Control); | 115 | const auto control = cache.GetEntry(game.title_id, FileSys::ContentRecordType::Control); |
| 116 | if (control != nullptr) | 116 | if (control != nullptr) |
| 117 | GetMetadataFromControlNCA(patch, *control, icon, name); | 117 | GetMetadataFromControlNCA(patch, *control, icon, name); |
| 118 | 118 | ||
| @@ -141,11 +141,11 @@ void GameListWorker::AddInstalledTitlesToGameList() { | |||
| 141 | emit EntryReady(list); | 141 | emit EntryReady(list); |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | const auto control_data = cache->ListEntriesFilter(FileSys::TitleType::Application, | 144 | const auto control_data = cache.ListEntriesFilter(FileSys::TitleType::Application, |
| 145 | FileSys::ContentRecordType::Control); | 145 | FileSys::ContentRecordType::Control); |
| 146 | 146 | ||
| 147 | for (const auto& entry : control_data) { | 147 | for (const auto& entry : control_data) { |
| 148 | auto nca = cache->GetEntry(entry); | 148 | auto nca = cache.GetEntry(entry); |
| 149 | if (nca != nullptr) { | 149 | if (nca != nullptr) { |
| 150 | nca_control_map.insert_or_assign(entry.title_id, std::move(nca)); | 150 | nca_control_map.insert_or_assign(entry.title_id, std::move(nca)); |
| 151 | } | 151 | } |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 93bf117c8..22c207a3a 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -518,6 +518,8 @@ void GMainWindow::OnDisplayTitleBars(bool show) { | |||
| 518 | QStringList GMainWindow::GetUnsupportedGLExtensions() { | 518 | QStringList GMainWindow::GetUnsupportedGLExtensions() { |
| 519 | QStringList unsupported_ext; | 519 | QStringList unsupported_ext; |
| 520 | 520 | ||
| 521 | if (!GLAD_GL_ARB_direct_state_access) | ||
| 522 | unsupported_ext.append("ARB_direct_state_access"); | ||
| 521 | if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) | 523 | if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) |
| 522 | unsupported_ext.append("ARB_vertex_type_10f_11f_11f_rev"); | 524 | unsupported_ext.append("ARB_vertex_type_10f_11f_11f_rev"); |
| 523 | if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) | 525 | if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) |
| @@ -905,7 +907,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 905 | } | 907 | } |
| 906 | 908 | ||
| 907 | const auto installed = Service::FileSystem::GetUnionContents(); | 909 | const auto installed = Service::FileSystem::GetUnionContents(); |
| 908 | auto romfs_title_id = SelectRomFSDumpTarget(*installed, program_id); | 910 | const auto romfs_title_id = SelectRomFSDumpTarget(installed, program_id); |
| 909 | 911 | ||
| 910 | if (!romfs_title_id) { | 912 | if (!romfs_title_id) { |
| 911 | failed(); | 913 | failed(); |
| @@ -920,7 +922,7 @@ void GMainWindow::OnGameListDumpRomFS(u64 program_id, const std::string& game_pa | |||
| 920 | if (*romfs_title_id == program_id) { | 922 | if (*romfs_title_id == program_id) { |
| 921 | romfs = file; | 923 | romfs = file; |
| 922 | } else { | 924 | } else { |
| 923 | romfs = installed->GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS(); | 925 | romfs = installed.GetEntry(*romfs_title_id, FileSys::ContentRecordType::Data)->GetRomFS(); |
| 924 | } | 926 | } |
| 925 | 927 | ||
| 926 | const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); | 928 | const auto extracted = FileSys::ExtractRomFS(romfs, FileSys::RomFSExtractionType::Full); |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 2d6f8cced..a557f2884 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -111,6 +111,8 @@ void EmuWindow_SDL2::Fullscreen() { | |||
| 111 | bool EmuWindow_SDL2::SupportsRequiredGLExtensions() { | 111 | bool EmuWindow_SDL2::SupportsRequiredGLExtensions() { |
| 112 | std::vector<std::string> unsupported_ext; | 112 | std::vector<std::string> unsupported_ext; |
| 113 | 113 | ||
| 114 | if (!GLAD_GL_ARB_direct_state_access) | ||
| 115 | unsupported_ext.push_back("ARB_direct_state_access"); | ||
| 114 | if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) | 116 | if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) |
| 115 | unsupported_ext.push_back("ARB_vertex_type_10f_11f_11f_rev"); | 117 | unsupported_ext.push_back("ARB_vertex_type_10f_11f_11f_rev"); |
| 116 | if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) | 118 | if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) |