diff options
Diffstat (limited to 'src')
35 files changed, 495 insertions, 329 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 2db28dcf0..ab05788d7 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -284,13 +284,18 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) { | |||
| 284 | 284 | ||
| 285 | std::vector<u8> HLERequestContext::ReadBuffer(int buffer_index) const { | 285 | std::vector<u8> HLERequestContext::ReadBuffer(int buffer_index) const { |
| 286 | std::vector<u8> buffer; | 286 | std::vector<u8> buffer; |
| 287 | const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[buffer_index].Size()}; | 287 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && |
| 288 | BufferDescriptorA()[buffer_index].Size()}; | ||
| 288 | auto& memory = Core::System::GetInstance().Memory(); | 289 | auto& memory = Core::System::GetInstance().Memory(); |
| 289 | 290 | ||
| 290 | if (is_buffer_a) { | 291 | if (is_buffer_a) { |
| 292 | ASSERT_MSG(BufferDescriptorA().size() > buffer_index, | ||
| 293 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | ||
| 291 | buffer.resize(BufferDescriptorA()[buffer_index].Size()); | 294 | buffer.resize(BufferDescriptorA()[buffer_index].Size()); |
| 292 | memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); | 295 | memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); |
| 293 | } else { | 296 | } else { |
| 297 | ASSERT_MSG(BufferDescriptorX().size() > buffer_index, | ||
| 298 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | ||
| 294 | buffer.resize(BufferDescriptorX()[buffer_index].Size()); | 299 | buffer.resize(BufferDescriptorX()[buffer_index].Size()); |
| 295 | memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); | 300 | memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); |
| 296 | } | 301 | } |
| @@ -305,7 +310,8 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, | |||
| 305 | return 0; | 310 | return 0; |
| 306 | } | 311 | } |
| 307 | 312 | ||
| 308 | const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[buffer_index].Size()}; | 313 | const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && |
| 314 | BufferDescriptorB()[buffer_index].Size()}; | ||
| 309 | const std::size_t buffer_size{GetWriteBufferSize(buffer_index)}; | 315 | const std::size_t buffer_size{GetWriteBufferSize(buffer_index)}; |
| 310 | if (size > buffer_size) { | 316 | if (size > buffer_size) { |
| 311 | LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, | 317 | LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, |
| @@ -315,8 +321,16 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, | |||
| 315 | 321 | ||
| 316 | auto& memory = Core::System::GetInstance().Memory(); | 322 | auto& memory = Core::System::GetInstance().Memory(); |
| 317 | if (is_buffer_b) { | 323 | if (is_buffer_b) { |
| 324 | ASSERT_MSG(BufferDescriptorB().size() > buffer_index, | ||
| 325 | "BufferDescriptorB invalid buffer_index {}", buffer_index); | ||
| 326 | ASSERT_MSG(BufferDescriptorB()[buffer_index].Size() >= size, | ||
| 327 | "BufferDescriptorB buffer_index {} is not large enough", buffer_index); | ||
| 318 | memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); | 328 | memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); |
| 319 | } else { | 329 | } else { |
| 330 | ASSERT_MSG(BufferDescriptorC().size() > buffer_index, | ||
| 331 | "BufferDescriptorC invalid buffer_index {}", buffer_index); | ||
| 332 | ASSERT_MSG(BufferDescriptorC()[buffer_index].Size() >= size, | ||
| 333 | "BufferDescriptorC buffer_index {} is not large enough", buffer_index); | ||
| 320 | memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); | 334 | memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); |
| 321 | } | 335 | } |
| 322 | 336 | ||
| @@ -324,15 +338,35 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, | |||
| 324 | } | 338 | } |
| 325 | 339 | ||
| 326 | std::size_t HLERequestContext::GetReadBufferSize(int buffer_index) const { | 340 | std::size_t HLERequestContext::GetReadBufferSize(int buffer_index) const { |
| 327 | const bool is_buffer_a{BufferDescriptorA().size() && BufferDescriptorA()[buffer_index].Size()}; | 341 | const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && |
| 328 | return is_buffer_a ? BufferDescriptorA()[buffer_index].Size() | 342 | BufferDescriptorA()[buffer_index].Size()}; |
| 329 | : BufferDescriptorX()[buffer_index].Size(); | 343 | if (is_buffer_a) { |
| 344 | ASSERT_MSG(BufferDescriptorA().size() > buffer_index, | ||
| 345 | "BufferDescriptorA invalid buffer_index {}", buffer_index); | ||
| 346 | ASSERT_MSG(BufferDescriptorA()[buffer_index].Size() > 0, | ||
| 347 | "BufferDescriptorA buffer_index {} is empty", buffer_index); | ||
| 348 | return BufferDescriptorA()[buffer_index].Size(); | ||
| 349 | } else { | ||
| 350 | ASSERT_MSG(BufferDescriptorX().size() > buffer_index, | ||
| 351 | "BufferDescriptorX invalid buffer_index {}", buffer_index); | ||
| 352 | ASSERT_MSG(BufferDescriptorX()[buffer_index].Size() > 0, | ||
| 353 | "BufferDescriptorX buffer_index {} is empty", buffer_index); | ||
| 354 | return BufferDescriptorX()[buffer_index].Size(); | ||
| 355 | } | ||
| 330 | } | 356 | } |
| 331 | 357 | ||
| 332 | std::size_t HLERequestContext::GetWriteBufferSize(int buffer_index) const { | 358 | std::size_t HLERequestContext::GetWriteBufferSize(int buffer_index) const { |
| 333 | const bool is_buffer_b{BufferDescriptorB().size() && BufferDescriptorB()[buffer_index].Size()}; | 359 | const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && |
| 334 | return is_buffer_b ? BufferDescriptorB()[buffer_index].Size() | 360 | BufferDescriptorB()[buffer_index].Size()}; |
| 335 | : BufferDescriptorC()[buffer_index].Size(); | 361 | if (is_buffer_b) { |
| 362 | ASSERT_MSG(BufferDescriptorB().size() > buffer_index, | ||
| 363 | "BufferDescriptorB invalid buffer_index {}", buffer_index); | ||
| 364 | return BufferDescriptorB()[buffer_index].Size(); | ||
| 365 | } else { | ||
| 366 | ASSERT_MSG(BufferDescriptorC().size() > buffer_index, | ||
| 367 | "BufferDescriptorC invalid buffer_index {}", buffer_index); | ||
| 368 | return BufferDescriptorC()[buffer_index].Size(); | ||
| 369 | } | ||
| 336 | } | 370 | } |
| 337 | 371 | ||
| 338 | std::string HLERequestContext::Description() const { | 372 | std::string HLERequestContext::Description() const { |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 1d99bf7a2..9cae5c73d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1863,10 +1863,14 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd | |||
| 1863 | } | 1863 | } |
| 1864 | 1864 | ||
| 1865 | auto& kernel = system.Kernel(); | 1865 | auto& kernel = system.Kernel(); |
| 1866 | auto transfer_mem_handle = TransferMemory::Create(kernel, addr, size, perms); | 1866 | auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms); |
| 1867 | |||
| 1868 | if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { | ||
| 1869 | return reserve_result; | ||
| 1870 | } | ||
| 1867 | 1871 | ||
| 1868 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 1872 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 1869 | const auto result = handle_table.Create(std::move(transfer_mem_handle)); | 1873 | const auto result{handle_table.Create(std::move(transfer_mem_handle))}; |
| 1870 | if (result.Failed()) { | 1874 | if (result.Failed()) { |
| 1871 | return result.Code(); | 1875 | return result.Code(); |
| 1872 | } | 1876 | } |
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp index f0e73f57b..f2d3f8b49 100644 --- a/src/core/hle/kernel/transfer_memory.cpp +++ b/src/core/hle/kernel/transfer_memory.cpp | |||
| @@ -8,15 +8,23 @@ | |||
| 8 | #include "core/hle/kernel/shared_memory.h" | 8 | #include "core/hle/kernel/shared_memory.h" |
| 9 | #include "core/hle/kernel/transfer_memory.h" | 9 | #include "core/hle/kernel/transfer_memory.h" |
| 10 | #include "core/hle/result.h" | 10 | #include "core/hle/result.h" |
| 11 | #include "core/memory.h" | ||
| 11 | 12 | ||
| 12 | namespace Kernel { | 13 | namespace Kernel { |
| 13 | 14 | ||
| 14 | TransferMemory::TransferMemory(KernelCore& kernel) : Object{kernel} {} | 15 | TransferMemory::TransferMemory(KernelCore& kernel, Memory::Memory& memory) |
| 15 | TransferMemory::~TransferMemory() = default; | 16 | : Object{kernel}, memory{memory} {} |
| 16 | 17 | ||
| 17 | std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address, | 18 | TransferMemory::~TransferMemory() { |
| 18 | u64 size, MemoryPermission permissions) { | 19 | // Release memory region when transfer memory is destroyed |
| 19 | std::shared_ptr<TransferMemory> transfer_memory{std::make_shared<TransferMemory>(kernel)}; | 20 | Reset(); |
| 21 | } | ||
| 22 | |||
| 23 | std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, Memory::Memory& memory, | ||
| 24 | VAddr base_address, u64 size, | ||
| 25 | MemoryPermission permissions) { | ||
| 26 | std::shared_ptr<TransferMemory> transfer_memory{ | ||
| 27 | std::make_shared<TransferMemory>(kernel, memory)}; | ||
| 20 | 28 | ||
| 21 | transfer_memory->base_address = base_address; | 29 | transfer_memory->base_address = base_address; |
| 22 | transfer_memory->memory_size = size; | 30 | transfer_memory->memory_size = size; |
| @@ -27,7 +35,7 @@ std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr | |||
| 27 | } | 35 | } |
| 28 | 36 | ||
| 29 | const u8* TransferMemory::GetPointer() const { | 37 | const u8* TransferMemory::GetPointer() const { |
| 30 | return backing_block.get()->data(); | 38 | return memory.GetPointer(base_address); |
| 31 | } | 39 | } |
| 32 | 40 | ||
| 33 | u64 TransferMemory::GetSize() const { | 41 | u64 TransferMemory::GetSize() const { |
| @@ -62,6 +70,52 @@ ResultCode TransferMemory::MapMemory(VAddr address, u64 size, MemoryPermission p | |||
| 62 | return RESULT_SUCCESS; | 70 | return RESULT_SUCCESS; |
| 63 | } | 71 | } |
| 64 | 72 | ||
| 73 | ResultCode TransferMemory::Reserve() { | ||
| 74 | auto& vm_manager{owner_process->VMManager()}; | ||
| 75 | const auto check_range_result{vm_manager.CheckRangeState( | ||
| 76 | base_address, memory_size, MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, | ||
| 77 | MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, VMAPermission::All, | ||
| 78 | VMAPermission::ReadWrite, MemoryAttribute::Mask, MemoryAttribute::None, | ||
| 79 | MemoryAttribute::IpcAndDeviceMapped)}; | ||
| 80 | |||
| 81 | if (check_range_result.Failed()) { | ||
| 82 | return check_range_result.Code(); | ||
| 83 | } | ||
| 84 | |||
| 85 | auto [state_, permissions_, attribute] = *check_range_result; | ||
| 86 | |||
| 87 | if (const auto result{vm_manager.ReprotectRange( | ||
| 88 | base_address, memory_size, SharedMemory::ConvertPermissions(owner_permissions))}; | ||
| 89 | result.IsError()) { | ||
| 90 | return result; | ||
| 91 | } | ||
| 92 | |||
| 93 | return vm_manager.SetMemoryAttribute(base_address, memory_size, MemoryAttribute::Mask, | ||
| 94 | attribute | MemoryAttribute::Locked); | ||
| 95 | } | ||
| 96 | |||
| 97 | ResultCode TransferMemory::Reset() { | ||
| 98 | auto& vm_manager{owner_process->VMManager()}; | ||
| 99 | if (const auto result{vm_manager.CheckRangeState( | ||
| 100 | base_address, memory_size, | ||
| 101 | MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, | ||
| 102 | MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, VMAPermission::None, | ||
| 103 | VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::Locked, | ||
| 104 | MemoryAttribute::IpcAndDeviceMapped)}; | ||
| 105 | result.Failed()) { | ||
| 106 | return result.Code(); | ||
| 107 | } | ||
| 108 | |||
| 109 | if (const auto result{ | ||
| 110 | vm_manager.ReprotectRange(base_address, memory_size, VMAPermission::ReadWrite)}; | ||
| 111 | result.IsError()) { | ||
| 112 | return result; | ||
| 113 | } | ||
| 114 | |||
| 115 | return vm_manager.SetMemoryAttribute(base_address, memory_size, MemoryAttribute::Mask, | ||
| 116 | MemoryAttribute::None); | ||
| 117 | } | ||
| 118 | |||
| 65 | ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) { | 119 | ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) { |
| 66 | if (memory_size != size) { | 120 | if (memory_size != size) { |
| 67 | return ERR_INVALID_SIZE; | 121 | return ERR_INVALID_SIZE; |
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h index 0a6e15d18..6e388536a 100644 --- a/src/core/hle/kernel/transfer_memory.h +++ b/src/core/hle/kernel/transfer_memory.h | |||
| @@ -11,6 +11,10 @@ | |||
| 11 | 11 | ||
| 12 | union ResultCode; | 12 | union ResultCode; |
| 13 | 13 | ||
| 14 | namespace Memory { | ||
| 15 | class Memory; | ||
| 16 | } | ||
| 17 | |||
| 14 | namespace Kernel { | 18 | namespace Kernel { |
| 15 | 19 | ||
| 16 | class KernelCore; | 20 | class KernelCore; |
| @@ -26,12 +30,13 @@ enum class MemoryPermission : u32; | |||
| 26 | /// | 30 | /// |
| 27 | class TransferMemory final : public Object { | 31 | class TransferMemory final : public Object { |
| 28 | public: | 32 | public: |
| 29 | explicit TransferMemory(KernelCore& kernel); | 33 | explicit TransferMemory(KernelCore& kernel, Memory::Memory& memory); |
| 30 | ~TransferMemory() override; | 34 | ~TransferMemory() override; |
| 31 | 35 | ||
| 32 | static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; | 36 | static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; |
| 33 | 37 | ||
| 34 | static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, u64 size, | 38 | static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Memory::Memory& memory, |
| 39 | VAddr base_address, u64 size, | ||
| 35 | MemoryPermission permissions); | 40 | MemoryPermission permissions); |
| 36 | 41 | ||
| 37 | TransferMemory(const TransferMemory&) = delete; | 42 | TransferMemory(const TransferMemory&) = delete; |
| @@ -80,6 +85,14 @@ public: | |||
| 80 | /// | 85 | /// |
| 81 | ResultCode UnmapMemory(VAddr address, u64 size); | 86 | ResultCode UnmapMemory(VAddr address, u64 size); |
| 82 | 87 | ||
| 88 | /// Reserves the region to be used for the transfer memory, called after the transfer memory is | ||
| 89 | /// created. | ||
| 90 | ResultCode Reserve(); | ||
| 91 | |||
| 92 | /// Resets the region previously used for the transfer memory, called after the transfer memory | ||
| 93 | /// is closed. | ||
| 94 | ResultCode Reset(); | ||
| 95 | |||
| 83 | private: | 96 | private: |
| 84 | /// Memory block backing this instance. | 97 | /// Memory block backing this instance. |
| 85 | std::shared_ptr<PhysicalMemory> backing_block; | 98 | std::shared_ptr<PhysicalMemory> backing_block; |
| @@ -98,6 +111,8 @@ private: | |||
| 98 | 111 | ||
| 99 | /// Whether or not this transfer memory instance has mapped memory. | 112 | /// Whether or not this transfer memory instance has mapped memory. |
| 100 | bool is_mapped = false; | 113 | bool is_mapped = false; |
| 114 | |||
| 115 | Memory::Memory& memory; | ||
| 101 | }; | 116 | }; |
| 102 | 117 | ||
| 103 | } // namespace Kernel | 118 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 0b3500fce..024c22901 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -544,7 +544,8 @@ MemoryInfo VMManager::QueryMemory(VAddr address) const { | |||
| 544 | 544 | ||
| 545 | ResultCode VMManager::SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask, | 545 | ResultCode VMManager::SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask, |
| 546 | MemoryAttribute attribute) { | 546 | MemoryAttribute attribute) { |
| 547 | constexpr auto ignore_mask = MemoryAttribute::Uncached | MemoryAttribute::DeviceMapped; | 547 | constexpr auto ignore_mask = |
| 548 | MemoryAttribute::Uncached | MemoryAttribute::DeviceMapped | MemoryAttribute::Locked; | ||
| 548 | constexpr auto attribute_mask = ~ignore_mask; | 549 | constexpr auto attribute_mask = ~ignore_mask; |
| 549 | 550 | ||
| 550 | const auto result = CheckRangeState( | 551 | const auto result = CheckRangeState( |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 850a7ebc3..90b4b006a 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -98,6 +98,8 @@ enum class MemoryAttribute : u32 { | |||
| 98 | DeviceMapped = 4, | 98 | DeviceMapped = 4, |
| 99 | /// Uncached memory | 99 | /// Uncached memory |
| 100 | Uncached = 8, | 100 | Uncached = 8, |
| 101 | |||
| 102 | IpcAndDeviceMapped = LockedForIPC | DeviceMapped, | ||
| 101 | }; | 103 | }; |
| 102 | 104 | ||
| 103 | constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) { | 105 | constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) { |
| @@ -654,6 +656,35 @@ public: | |||
| 654 | /// is scheduled. | 656 | /// is scheduled. |
| 655 | Common::PageTable page_table{Memory::PAGE_BITS}; | 657 | Common::PageTable page_table{Memory::PAGE_BITS}; |
| 656 | 658 | ||
| 659 | using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>; | ||
| 660 | |||
| 661 | /// Checks if an address range adheres to the specified states provided. | ||
| 662 | /// | ||
| 663 | /// @param address The starting address of the address range. | ||
| 664 | /// @param size The size of the address range. | ||
| 665 | /// @param state_mask The memory state mask. | ||
| 666 | /// @param state The state to compare the individual VMA states against, | ||
| 667 | /// which is done in the form of: (vma.state & state_mask) != state. | ||
| 668 | /// @param permission_mask The memory permissions mask. | ||
| 669 | /// @param permissions The permission to compare the individual VMA permissions against, | ||
| 670 | /// which is done in the form of: | ||
| 671 | /// (vma.permission & permission_mask) != permission. | ||
| 672 | /// @param attribute_mask The memory attribute mask. | ||
| 673 | /// @param attribute The memory attributes to compare the individual VMA attributes | ||
| 674 | /// against, which is done in the form of: | ||
| 675 | /// (vma.attributes & attribute_mask) != attribute. | ||
| 676 | /// @param ignore_mask The memory attributes to ignore during the check. | ||
| 677 | /// | ||
| 678 | /// @returns If successful, returns a tuple containing the memory attributes | ||
| 679 | /// (with ignored bits specified by ignore_mask unset), memory permissions, and | ||
| 680 | /// memory state across the memory range. | ||
| 681 | /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE. | ||
| 682 | /// | ||
| 683 | CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state, | ||
| 684 | VMAPermission permission_mask, VMAPermission permissions, | ||
| 685 | MemoryAttribute attribute_mask, MemoryAttribute attribute, | ||
| 686 | MemoryAttribute ignore_mask) const; | ||
| 687 | |||
| 657 | private: | 688 | private: |
| 658 | using VMAIter = VMAMap::iterator; | 689 | using VMAIter = VMAMap::iterator; |
| 659 | 690 | ||
| @@ -707,35 +738,6 @@ private: | |||
| 707 | /// Clears out the page table | 738 | /// Clears out the page table |
| 708 | void ClearPageTable(); | 739 | void ClearPageTable(); |
| 709 | 740 | ||
| 710 | using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>; | ||
| 711 | |||
| 712 | /// Checks if an address range adheres to the specified states provided. | ||
| 713 | /// | ||
| 714 | /// @param address The starting address of the address range. | ||
| 715 | /// @param size The size of the address range. | ||
| 716 | /// @param state_mask The memory state mask. | ||
| 717 | /// @param state The state to compare the individual VMA states against, | ||
| 718 | /// which is done in the form of: (vma.state & state_mask) != state. | ||
| 719 | /// @param permission_mask The memory permissions mask. | ||
| 720 | /// @param permissions The permission to compare the individual VMA permissions against, | ||
| 721 | /// which is done in the form of: | ||
| 722 | /// (vma.permission & permission_mask) != permission. | ||
| 723 | /// @param attribute_mask The memory attribute mask. | ||
| 724 | /// @param attribute The memory attributes to compare the individual VMA attributes | ||
| 725 | /// against, which is done in the form of: | ||
| 726 | /// (vma.attributes & attribute_mask) != attribute. | ||
| 727 | /// @param ignore_mask The memory attributes to ignore during the check. | ||
| 728 | /// | ||
| 729 | /// @returns If successful, returns a tuple containing the memory attributes | ||
| 730 | /// (with ignored bits specified by ignore_mask unset), memory permissions, and | ||
| 731 | /// memory state across the memory range. | ||
| 732 | /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE. | ||
| 733 | /// | ||
| 734 | CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state, | ||
| 735 | VMAPermission permission_mask, VMAPermission permissions, | ||
| 736 | MemoryAttribute attribute_mask, MemoryAttribute attribute, | ||
| 737 | MemoryAttribute ignore_mask) const; | ||
| 738 | |||
| 739 | /// Gets the amount of memory currently mapped (state != Unmapped) in a range. | 741 | /// Gets the amount of memory currently mapped (state != Unmapped) in a range. |
| 740 | ResultVal<std::size_t> SizeOfAllocatedVMAsInRange(VAddr address, std::size_t size) const; | 742 | ResultVal<std::size_t> SizeOfAllocatedVMAsInRange(VAddr address, std::size_t size) const; |
| 741 | 743 | ||
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index a0c806e8f..1838260fd 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp | |||
| @@ -50,17 +50,8 @@ std::shared_ptr<Thread> WaitObject::GetHighestPriorityReadyThread() const { | |||
| 50 | if (ShouldWait(thread.get())) | 50 | if (ShouldWait(thread.get())) |
| 51 | continue; | 51 | continue; |
| 52 | 52 | ||
| 53 | // A thread is ready to run if it's either in ThreadStatus::WaitSynch | 53 | candidate = thread.get(); |
| 54 | // and the rest of the objects it is waiting on are ready. | 54 | candidate_priority = thread->GetPriority(); |
| 55 | bool ready_to_run = true; | ||
| 56 | if (thread_status == ThreadStatus::WaitSynch) { | ||
| 57 | ready_to_run = thread->AllWaitObjectsReady(); | ||
| 58 | } | ||
| 59 | |||
| 60 | if (ready_to_run) { | ||
| 61 | candidate = thread.get(); | ||
| 62 | candidate_priority = thread->GetPriority(); | ||
| 63 | } | ||
| 64 | } | 55 | } |
| 65 | 56 | ||
| 66 | return SharedFrom(candidate); | 57 | return SharedFrom(candidate); |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 95aa5d23d..cc978713b 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -709,8 +709,34 @@ void ICommonStateGetter::SetCpuBoostMode(Kernel::HLERequestContext& ctx) { | |||
| 709 | apm_sys->SetCpuBoostMode(ctx); | 709 | apm_sys->SetCpuBoostMode(ctx); |
| 710 | } | 710 | } |
| 711 | 711 | ||
| 712 | IStorage::IStorage(std::vector<u8> buffer) | 712 | IStorageImpl::~IStorageImpl() = default; |
| 713 | : ServiceFramework("IStorage"), buffer(std::move(buffer)) { | 713 | |
| 714 | class StorageDataImpl final : public IStorageImpl { | ||
| 715 | public: | ||
| 716 | explicit StorageDataImpl(std::vector<u8>&& buffer) : buffer{std::move(buffer)} {} | ||
| 717 | |||
| 718 | std::vector<u8>& GetData() override { | ||
| 719 | return buffer; | ||
| 720 | } | ||
| 721 | |||
| 722 | const std::vector<u8>& GetData() const override { | ||
| 723 | return buffer; | ||
| 724 | } | ||
| 725 | |||
| 726 | std::size_t GetSize() const override { | ||
| 727 | return buffer.size(); | ||
| 728 | } | ||
| 729 | |||
| 730 | private: | ||
| 731 | std::vector<u8> buffer; | ||
| 732 | }; | ||
| 733 | |||
| 734 | IStorage::IStorage(std::vector<u8>&& buffer) | ||
| 735 | : ServiceFramework("IStorage"), impl{std::make_shared<StorageDataImpl>(std::move(buffer))} { | ||
| 736 | Register(); | ||
| 737 | } | ||
| 738 | |||
| 739 | void IStorage::Register() { | ||
| 714 | // clang-format off | 740 | // clang-format off |
| 715 | static const FunctionInfo functions[] = { | 741 | static const FunctionInfo functions[] = { |
| 716 | {0, &IStorage::Open, "Open"}, | 742 | {0, &IStorage::Open, "Open"}, |
| @@ -723,8 +749,13 @@ IStorage::IStorage(std::vector<u8> buffer) | |||
| 723 | 749 | ||
| 724 | IStorage::~IStorage() = default; | 750 | IStorage::~IStorage() = default; |
| 725 | 751 | ||
| 726 | const std::vector<u8>& IStorage::GetData() const { | 752 | void IStorage::Open(Kernel::HLERequestContext& ctx) { |
| 727 | return buffer; | 753 | LOG_DEBUG(Service_AM, "called"); |
| 754 | |||
| 755 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 756 | |||
| 757 | rb.Push(RESULT_SUCCESS); | ||
| 758 | rb.PushIpcInterface<IStorageAccessor>(*this); | ||
| 728 | } | 759 | } |
| 729 | 760 | ||
| 730 | void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { | 761 | void ICommonStateGetter::GetOperationMode(Kernel::HLERequestContext& ctx) { |
| @@ -816,7 +847,7 @@ private: | |||
| 816 | LOG_DEBUG(Service_AM, "called"); | 847 | LOG_DEBUG(Service_AM, "called"); |
| 817 | 848 | ||
| 818 | IPC::RequestParser rp{ctx}; | 849 | IPC::RequestParser rp{ctx}; |
| 819 | applet->GetBroker().PushNormalDataFromGame(*rp.PopIpcInterface<IStorage>()); | 850 | applet->GetBroker().PushNormalDataFromGame(rp.PopIpcInterface<IStorage>()); |
| 820 | 851 | ||
| 821 | IPC::ResponseBuilder rb{ctx, 2}; | 852 | IPC::ResponseBuilder rb{ctx, 2}; |
| 822 | rb.Push(RESULT_SUCCESS); | 853 | rb.Push(RESULT_SUCCESS); |
| @@ -825,26 +856,25 @@ private: | |||
| 825 | void PopOutData(Kernel::HLERequestContext& ctx) { | 856 | void PopOutData(Kernel::HLERequestContext& ctx) { |
| 826 | LOG_DEBUG(Service_AM, "called"); | 857 | LOG_DEBUG(Service_AM, "called"); |
| 827 | 858 | ||
| 828 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 829 | |||
| 830 | const auto storage = applet->GetBroker().PopNormalDataToGame(); | 859 | const auto storage = applet->GetBroker().PopNormalDataToGame(); |
| 831 | if (storage == nullptr) { | 860 | if (storage == nullptr) { |
| 832 | LOG_ERROR(Service_AM, | 861 | LOG_ERROR(Service_AM, |
| 833 | "storage is a nullptr. There is no data in the current normal channel"); | 862 | "storage is a nullptr. There is no data in the current normal channel"); |
| 834 | 863 | IPC::ResponseBuilder rb{ctx, 2}; | |
| 835 | rb.Push(ERR_NO_DATA_IN_CHANNEL); | 864 | rb.Push(ERR_NO_DATA_IN_CHANNEL); |
| 836 | return; | 865 | return; |
| 837 | } | 866 | } |
| 838 | 867 | ||
| 868 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 839 | rb.Push(RESULT_SUCCESS); | 869 | rb.Push(RESULT_SUCCESS); |
| 840 | rb.PushIpcInterface<IStorage>(std::move(*storage)); | 870 | rb.PushIpcInterface<IStorage>(std::move(storage)); |
| 841 | } | 871 | } |
| 842 | 872 | ||
| 843 | void PushInteractiveInData(Kernel::HLERequestContext& ctx) { | 873 | void PushInteractiveInData(Kernel::HLERequestContext& ctx) { |
| 844 | LOG_DEBUG(Service_AM, "called"); | 874 | LOG_DEBUG(Service_AM, "called"); |
| 845 | 875 | ||
| 846 | IPC::RequestParser rp{ctx}; | 876 | IPC::RequestParser rp{ctx}; |
| 847 | applet->GetBroker().PushInteractiveDataFromGame(*rp.PopIpcInterface<IStorage>()); | 877 | applet->GetBroker().PushInteractiveDataFromGame(rp.PopIpcInterface<IStorage>()); |
| 848 | 878 | ||
| 849 | ASSERT(applet->IsInitialized()); | 879 | ASSERT(applet->IsInitialized()); |
| 850 | applet->ExecuteInteractive(); | 880 | applet->ExecuteInteractive(); |
| @@ -857,19 +887,18 @@ private: | |||
| 857 | void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { | 887 | void PopInteractiveOutData(Kernel::HLERequestContext& ctx) { |
| 858 | LOG_DEBUG(Service_AM, "called"); | 888 | LOG_DEBUG(Service_AM, "called"); |
| 859 | 889 | ||
| 860 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 861 | |||
| 862 | const auto storage = applet->GetBroker().PopInteractiveDataToGame(); | 890 | const auto storage = applet->GetBroker().PopInteractiveDataToGame(); |
| 863 | if (storage == nullptr) { | 891 | if (storage == nullptr) { |
| 864 | LOG_ERROR(Service_AM, | 892 | LOG_ERROR(Service_AM, |
| 865 | "storage is a nullptr. There is no data in the current interactive channel"); | 893 | "storage is a nullptr. There is no data in the current interactive channel"); |
| 866 | 894 | IPC::ResponseBuilder rb{ctx, 2}; | |
| 867 | rb.Push(ERR_NO_DATA_IN_CHANNEL); | 895 | rb.Push(ERR_NO_DATA_IN_CHANNEL); |
| 868 | return; | 896 | return; |
| 869 | } | 897 | } |
| 870 | 898 | ||
| 899 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 871 | rb.Push(RESULT_SUCCESS); | 900 | rb.Push(RESULT_SUCCESS); |
| 872 | rb.PushIpcInterface<IStorage>(std::move(*storage)); | 901 | rb.PushIpcInterface<IStorage>(std::move(storage)); |
| 873 | } | 902 | } |
| 874 | 903 | ||
| 875 | void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) { | 904 | void GetPopOutDataEvent(Kernel::HLERequestContext& ctx) { |
| @@ -891,15 +920,6 @@ private: | |||
| 891 | std::shared_ptr<Applets::Applet> applet; | 920 | std::shared_ptr<Applets::Applet> applet; |
| 892 | }; | 921 | }; |
| 893 | 922 | ||
| 894 | void IStorage::Open(Kernel::HLERequestContext& ctx) { | ||
| 895 | LOG_DEBUG(Service_AM, "called"); | ||
| 896 | |||
| 897 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||
| 898 | |||
| 899 | rb.Push(RESULT_SUCCESS); | ||
| 900 | rb.PushIpcInterface<IStorageAccessor>(*this); | ||
| 901 | } | ||
| 902 | |||
| 903 | IStorageAccessor::IStorageAccessor(IStorage& storage) | 923 | IStorageAccessor::IStorageAccessor(IStorage& storage) |
| 904 | : ServiceFramework("IStorageAccessor"), backing(storage) { | 924 | : ServiceFramework("IStorageAccessor"), backing(storage) { |
| 905 | // clang-format off | 925 | // clang-format off |
| @@ -921,7 +941,7 @@ void IStorageAccessor::GetSize(Kernel::HLERequestContext& ctx) { | |||
| 921 | IPC::ResponseBuilder rb{ctx, 4}; | 941 | IPC::ResponseBuilder rb{ctx, 4}; |
| 922 | 942 | ||
| 923 | rb.Push(RESULT_SUCCESS); | 943 | rb.Push(RESULT_SUCCESS); |
| 924 | rb.Push(static_cast<u64>(backing.buffer.size())); | 944 | rb.Push(static_cast<u64>(backing.GetSize())); |
| 925 | } | 945 | } |
| 926 | 946 | ||
| 927 | void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { | 947 | void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { |
| @@ -932,17 +952,17 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { | |||
| 932 | 952 | ||
| 933 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size()); | 953 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, data.size()); |
| 934 | 954 | ||
| 935 | if (data.size() > backing.buffer.size() - offset) { | 955 | if (data.size() > backing.GetSize() - offset) { |
| 936 | LOG_ERROR(Service_AM, | 956 | LOG_ERROR(Service_AM, |
| 937 | "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}", | 957 | "offset is out of bounds, backing_buffer_sz={}, data_size={}, offset={}", |
| 938 | backing.buffer.size(), data.size(), offset); | 958 | backing.GetSize(), data.size(), offset); |
| 939 | 959 | ||
| 940 | IPC::ResponseBuilder rb{ctx, 2}; | 960 | IPC::ResponseBuilder rb{ctx, 2}; |
| 941 | rb.Push(ERR_SIZE_OUT_OF_BOUNDS); | 961 | rb.Push(ERR_SIZE_OUT_OF_BOUNDS); |
| 942 | return; | 962 | return; |
| 943 | } | 963 | } |
| 944 | 964 | ||
| 945 | std::memcpy(backing.buffer.data() + offset, data.data(), data.size()); | 965 | std::memcpy(backing.GetData().data() + offset, data.data(), data.size()); |
| 946 | 966 | ||
| 947 | IPC::ResponseBuilder rb{ctx, 2}; | 967 | IPC::ResponseBuilder rb{ctx, 2}; |
| 948 | rb.Push(RESULT_SUCCESS); | 968 | rb.Push(RESULT_SUCCESS); |
| @@ -956,16 +976,16 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { | |||
| 956 | 976 | ||
| 957 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); | 977 | LOG_DEBUG(Service_AM, "called, offset={}, size={}", offset, size); |
| 958 | 978 | ||
| 959 | if (size > backing.buffer.size() - offset) { | 979 | if (size > backing.GetSize() - offset) { |
| 960 | LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}", | 980 | LOG_ERROR(Service_AM, "offset is out of bounds, backing_buffer_sz={}, size={}, offset={}", |
| 961 | backing.buffer.size(), size, offset); | 981 | backing.GetSize(), size, offset); |
| 962 | 982 | ||
| 963 | IPC::ResponseBuilder rb{ctx, 2}; | 983 | IPC::ResponseBuilder rb{ctx, 2}; |
| 964 | rb.Push(ERR_SIZE_OUT_OF_BOUNDS); | 984 | rb.Push(ERR_SIZE_OUT_OF_BOUNDS); |
| 965 | return; | 985 | return; |
| 966 | } | 986 | } |
| 967 | 987 | ||
| 968 | ctx.WriteBuffer(backing.buffer.data() + offset, size); | 988 | ctx.WriteBuffer(backing.GetData().data() + offset, size); |
| 969 | 989 | ||
| 970 | IPC::ResponseBuilder rb{ctx, 2}; | 990 | IPC::ResponseBuilder rb{ctx, 2}; |
| 971 | rb.Push(RESULT_SUCCESS); | 991 | rb.Push(RESULT_SUCCESS); |
| @@ -1031,7 +1051,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex | |||
| 1031 | rp.SetCurrentOffset(3); | 1051 | rp.SetCurrentOffset(3); |
| 1032 | const auto handle{rp.Pop<Kernel::Handle>()}; | 1052 | const auto handle{rp.Pop<Kernel::Handle>()}; |
| 1033 | 1053 | ||
| 1034 | const auto transfer_mem = | 1054 | auto transfer_mem = |
| 1035 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); | 1055 | system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle); |
| 1036 | 1056 | ||
| 1037 | if (transfer_mem == nullptr) { | 1057 | if (transfer_mem == nullptr) { |
| @@ -1047,7 +1067,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex | |||
| 1047 | 1067 | ||
| 1048 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1068 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1049 | rb.Push(RESULT_SUCCESS); | 1069 | rb.Push(RESULT_SUCCESS); |
| 1050 | rb.PushIpcInterface(std::make_shared<IStorage>(std::move(memory))); | 1070 | rb.PushIpcInterface<IStorage>(std::move(memory)); |
| 1051 | } | 1071 | } |
| 1052 | 1072 | ||
| 1053 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) | 1073 | IApplicationFunctions::IApplicationFunctions(Core::System& system_) |
| @@ -1189,13 +1209,11 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { | |||
| 1189 | u64 build_id{}; | 1209 | u64 build_id{}; |
| 1190 | std::memcpy(&build_id, build_id_full.data(), sizeof(u64)); | 1210 | std::memcpy(&build_id, build_id_full.data(), sizeof(u64)); |
| 1191 | 1211 | ||
| 1192 | const auto data = | 1212 | auto data = backend->GetLaunchParameter({system.CurrentProcess()->GetTitleID(), build_id}); |
| 1193 | backend->GetLaunchParameter({system.CurrentProcess()->GetTitleID(), build_id}); | ||
| 1194 | |||
| 1195 | if (data.has_value()) { | 1213 | if (data.has_value()) { |
| 1196 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1214 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1197 | rb.Push(RESULT_SUCCESS); | 1215 | rb.Push(RESULT_SUCCESS); |
| 1198 | rb.PushIpcInterface<AM::IStorage>(*data); | 1216 | rb.PushIpcInterface<IStorage>(std::move(*data)); |
| 1199 | launch_popped_application_specific = true; | 1217 | launch_popped_application_specific = true; |
| 1200 | return; | 1218 | return; |
| 1201 | } | 1219 | } |
| @@ -1218,7 +1236,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { | |||
| 1218 | std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); | 1236 | std::vector<u8> buffer(sizeof(LaunchParameterAccountPreselectedUser)); |
| 1219 | std::memcpy(buffer.data(), ¶ms, buffer.size()); | 1237 | std::memcpy(buffer.data(), ¶ms, buffer.size()); |
| 1220 | 1238 | ||
| 1221 | rb.PushIpcInterface<AM::IStorage>(buffer); | 1239 | rb.PushIpcInterface<IStorage>(std::move(buffer)); |
| 1222 | launch_popped_account_preselect = true; | 1240 | launch_popped_account_preselect = true; |
| 1223 | return; | 1241 | return; |
| 1224 | } | 1242 | } |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 448817be9..0b9a4332d 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -12,7 +12,8 @@ | |||
| 12 | 12 | ||
| 13 | namespace Kernel { | 13 | namespace Kernel { |
| 14 | class KernelCore; | 14 | class KernelCore; |
| 15 | } | 15 | class TransferMemory; |
| 16 | } // namespace Kernel | ||
| 16 | 17 | ||
| 17 | namespace Service::NVFlinger { | 18 | namespace Service::NVFlinger { |
| 18 | class NVFlinger; | 19 | class NVFlinger; |
| @@ -188,19 +189,36 @@ private: | |||
| 188 | std::shared_ptr<AppletMessageQueue> msg_queue; | 189 | std::shared_ptr<AppletMessageQueue> msg_queue; |
| 189 | }; | 190 | }; |
| 190 | 191 | ||
| 192 | class IStorageImpl { | ||
| 193 | public: | ||
| 194 | virtual ~IStorageImpl(); | ||
| 195 | virtual std::vector<u8>& GetData() = 0; | ||
| 196 | virtual const std::vector<u8>& GetData() const = 0; | ||
| 197 | virtual std::size_t GetSize() const = 0; | ||
| 198 | }; | ||
| 199 | |||
| 191 | class IStorage final : public ServiceFramework<IStorage> { | 200 | class IStorage final : public ServiceFramework<IStorage> { |
| 192 | public: | 201 | public: |
| 193 | explicit IStorage(std::vector<u8> buffer); | 202 | explicit IStorage(std::vector<u8>&& buffer); |
| 194 | ~IStorage() override; | 203 | ~IStorage() override; |
| 195 | 204 | ||
| 196 | const std::vector<u8>& GetData() const; | 205 | std::vector<u8>& GetData() { |
| 206 | return impl->GetData(); | ||
| 207 | } | ||
| 208 | |||
| 209 | const std::vector<u8>& GetData() const { | ||
| 210 | return impl->GetData(); | ||
| 211 | } | ||
| 212 | |||
| 213 | std::size_t GetSize() const { | ||
| 214 | return impl->GetSize(); | ||
| 215 | } | ||
| 197 | 216 | ||
| 198 | private: | 217 | private: |
| 218 | void Register(); | ||
| 199 | void Open(Kernel::HLERequestContext& ctx); | 219 | void Open(Kernel::HLERequestContext& ctx); |
| 200 | 220 | ||
| 201 | std::vector<u8> buffer; | 221 | std::shared_ptr<IStorageImpl> impl; |
| 202 | |||
| 203 | friend class IStorageAccessor; | ||
| 204 | }; | 222 | }; |
| 205 | 223 | ||
| 206 | class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { | 224 | class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { |
diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 92f995f8f..c3261f3e6 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp | |||
| @@ -50,16 +50,17 @@ AppletDataBroker::RawChannelData AppletDataBroker::PeekDataToAppletForDebug() co | |||
| 50 | return {std::move(out_normal), std::move(out_interactive)}; | 50 | return {std::move(out_normal), std::move(out_interactive)}; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() { | 53 | std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() { |
| 54 | if (out_channel.empty()) | 54 | if (out_channel.empty()) |
| 55 | return nullptr; | 55 | return nullptr; |
| 56 | 56 | ||
| 57 | auto out = std::move(out_channel.front()); | 57 | auto out = std::move(out_channel.front()); |
| 58 | out_channel.pop_front(); | 58 | out_channel.pop_front(); |
| 59 | pop_out_data_event.writable->Clear(); | ||
| 59 | return out; | 60 | return out; |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() { | 63 | std::shared_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() { |
| 63 | if (in_channel.empty()) | 64 | if (in_channel.empty()) |
| 64 | return nullptr; | 65 | return nullptr; |
| 65 | 66 | ||
| @@ -68,16 +69,17 @@ std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() { | |||
| 68 | return out; | 69 | return out; |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() { | 72 | std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() { |
| 72 | if (out_interactive_channel.empty()) | 73 | if (out_interactive_channel.empty()) |
| 73 | return nullptr; | 74 | return nullptr; |
| 74 | 75 | ||
| 75 | auto out = std::move(out_interactive_channel.front()); | 76 | auto out = std::move(out_interactive_channel.front()); |
| 76 | out_interactive_channel.pop_front(); | 77 | out_interactive_channel.pop_front(); |
| 78 | pop_interactive_out_data_event.writable->Clear(); | ||
| 77 | return out; | 79 | return out; |
| 78 | } | 80 | } |
| 79 | 81 | ||
| 80 | std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() { | 82 | std::shared_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() { |
| 81 | if (in_interactive_channel.empty()) | 83 | if (in_interactive_channel.empty()) |
| 82 | return nullptr; | 84 | return nullptr; |
| 83 | 85 | ||
| @@ -86,21 +88,21 @@ std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() { | |||
| 86 | return out; | 88 | return out; |
| 87 | } | 89 | } |
| 88 | 90 | ||
| 89 | void AppletDataBroker::PushNormalDataFromGame(IStorage storage) { | 91 | void AppletDataBroker::PushNormalDataFromGame(std::shared_ptr<IStorage>&& storage) { |
| 90 | in_channel.push_back(std::make_unique<IStorage>(storage)); | 92 | in_channel.emplace_back(std::move(storage)); |
| 91 | } | 93 | } |
| 92 | 94 | ||
| 93 | void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) { | 95 | void AppletDataBroker::PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage) { |
| 94 | out_channel.push_back(std::make_unique<IStorage>(storage)); | 96 | out_channel.emplace_back(std::move(storage)); |
| 95 | pop_out_data_event.writable->Signal(); | 97 | pop_out_data_event.writable->Signal(); |
| 96 | } | 98 | } |
| 97 | 99 | ||
| 98 | void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) { | 100 | void AppletDataBroker::PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage) { |
| 99 | in_interactive_channel.push_back(std::make_unique<IStorage>(storage)); | 101 | in_interactive_channel.emplace_back(std::move(storage)); |
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) { | 104 | void AppletDataBroker::PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage) { |
| 103 | out_interactive_channel.push_back(std::make_unique<IStorage>(storage)); | 105 | out_interactive_channel.emplace_back(std::move(storage)); |
| 104 | pop_interactive_out_data_event.writable->Signal(); | 106 | pop_interactive_out_data_event.writable->Signal(); |
| 105 | } | 107 | } |
| 106 | 108 | ||
diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 16e61fc6f..e75be86a2 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h | |||
| @@ -72,17 +72,17 @@ public: | |||
| 72 | // Retrieves but does not pop the data sent to applet. | 72 | // Retrieves but does not pop the data sent to applet. |
| 73 | RawChannelData PeekDataToAppletForDebug() const; | 73 | RawChannelData PeekDataToAppletForDebug() const; |
| 74 | 74 | ||
| 75 | std::unique_ptr<IStorage> PopNormalDataToGame(); | 75 | std::shared_ptr<IStorage> PopNormalDataToGame(); |
| 76 | std::unique_ptr<IStorage> PopNormalDataToApplet(); | 76 | std::shared_ptr<IStorage> PopNormalDataToApplet(); |
| 77 | 77 | ||
| 78 | std::unique_ptr<IStorage> PopInteractiveDataToGame(); | 78 | std::shared_ptr<IStorage> PopInteractiveDataToGame(); |
| 79 | std::unique_ptr<IStorage> PopInteractiveDataToApplet(); | 79 | std::shared_ptr<IStorage> PopInteractiveDataToApplet(); |
| 80 | 80 | ||
| 81 | void PushNormalDataFromGame(IStorage storage); | 81 | void PushNormalDataFromGame(std::shared_ptr<IStorage>&& storage); |
| 82 | void PushNormalDataFromApplet(IStorage storage); | 82 | void PushNormalDataFromApplet(std::shared_ptr<IStorage>&& storage); |
| 83 | 83 | ||
| 84 | void PushInteractiveDataFromGame(IStorage storage); | 84 | void PushInteractiveDataFromGame(std::shared_ptr<IStorage>&& storage); |
| 85 | void PushInteractiveDataFromApplet(IStorage storage); | 85 | void PushInteractiveDataFromApplet(std::shared_ptr<IStorage>&& storage); |
| 86 | 86 | ||
| 87 | void SignalStateChanged() const; | 87 | void SignalStateChanged() const; |
| 88 | 88 | ||
| @@ -94,16 +94,16 @@ private: | |||
| 94 | // Queues are named from applet's perspective | 94 | // Queues are named from applet's perspective |
| 95 | 95 | ||
| 96 | // PopNormalDataToApplet and PushNormalDataFromGame | 96 | // PopNormalDataToApplet and PushNormalDataFromGame |
| 97 | std::deque<std::unique_ptr<IStorage>> in_channel; | 97 | std::deque<std::shared_ptr<IStorage>> in_channel; |
| 98 | 98 | ||
| 99 | // PopNormalDataToGame and PushNormalDataFromApplet | 99 | // PopNormalDataToGame and PushNormalDataFromApplet |
| 100 | std::deque<std::unique_ptr<IStorage>> out_channel; | 100 | std::deque<std::shared_ptr<IStorage>> out_channel; |
| 101 | 101 | ||
| 102 | // PopInteractiveDataToApplet and PushInteractiveDataFromGame | 102 | // PopInteractiveDataToApplet and PushInteractiveDataFromGame |
| 103 | std::deque<std::unique_ptr<IStorage>> in_interactive_channel; | 103 | std::deque<std::shared_ptr<IStorage>> in_interactive_channel; |
| 104 | 104 | ||
| 105 | // PopInteractiveDataToGame and PushInteractiveDataFromApplet | 105 | // PopInteractiveDataToGame and PushInteractiveDataFromApplet |
| 106 | std::deque<std::unique_ptr<IStorage>> out_interactive_channel; | 106 | std::deque<std::shared_ptr<IStorage>> out_interactive_channel; |
| 107 | 107 | ||
| 108 | Kernel::EventPair state_changed_event; | 108 | Kernel::EventPair state_changed_event; |
| 109 | 109 | ||
diff --git a/src/core/hle/service/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index eab0d42c9..f12fd7f89 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp | |||
| @@ -186,7 +186,7 @@ void Error::Execute() { | |||
| 186 | 186 | ||
| 187 | void Error::DisplayCompleted() { | 187 | void Error::DisplayCompleted() { |
| 188 | complete = true; | 188 | complete = true; |
| 189 | broker.PushNormalDataFromApplet(IStorage{{}}); | 189 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{})); |
| 190 | broker.SignalStateChanged(); | 190 | broker.SignalStateChanged(); |
| 191 | } | 191 | } |
| 192 | 192 | ||
diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index 328438a1d..104501ac5 100644 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp | |||
| @@ -20,7 +20,7 @@ namespace Service::AM::Applets { | |||
| 20 | constexpr ResultCode ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; | 20 | constexpr ResultCode ERROR_INVALID_PIN{ErrorModule::PCTL, 221}; |
| 21 | 21 | ||
| 22 | static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) { | 22 | static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) { |
| 23 | std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet(); | 23 | std::shared_ptr<IStorage> storage = broker.PopNormalDataToApplet(); |
| 24 | for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) { | 24 | for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) { |
| 25 | const auto data = storage->GetData(); | 25 | const auto data = storage->GetData(); |
| 26 | LOG_INFO(Service_AM, | 26 | LOG_INFO(Service_AM, |
| @@ -148,7 +148,7 @@ void Auth::AuthFinished(bool successful) { | |||
| 148 | std::vector<u8> out(sizeof(Return)); | 148 | std::vector<u8> out(sizeof(Return)); |
| 149 | std::memcpy(out.data(), &return_, sizeof(Return)); | 149 | std::memcpy(out.data(), &return_, sizeof(Return)); |
| 150 | 150 | ||
| 151 | broker.PushNormalDataFromApplet(IStorage{out}); | 151 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(out))); |
| 152 | broker.SignalStateChanged(); | 152 | broker.SignalStateChanged(); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| @@ -198,7 +198,7 @@ void PhotoViewer::Execute() { | |||
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | void PhotoViewer::ViewFinished() { | 200 | void PhotoViewer::ViewFinished() { |
| 201 | broker.PushNormalDataFromApplet(IStorage{{}}); | 201 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>{})); |
| 202 | broker.SignalStateChanged(); | 202 | broker.SignalStateChanged(); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| @@ -234,8 +234,8 @@ void StubApplet::ExecuteInteractive() { | |||
| 234 | LOG_WARNING(Service_AM, "called (STUBBED)"); | 234 | LOG_WARNING(Service_AM, "called (STUBBED)"); |
| 235 | LogCurrentStorage(broker, "ExecuteInteractive"); | 235 | LogCurrentStorage(broker, "ExecuteInteractive"); |
| 236 | 236 | ||
| 237 | broker.PushNormalDataFromApplet(IStorage{std::vector<u8>(0x1000)}); | 237 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); |
| 238 | broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)}); | 238 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); |
| 239 | broker.SignalStateChanged(); | 239 | broker.SignalStateChanged(); |
| 240 | } | 240 | } |
| 241 | 241 | ||
| @@ -243,8 +243,8 @@ void StubApplet::Execute() { | |||
| 243 | LOG_WARNING(Service_AM, "called (STUBBED)"); | 243 | LOG_WARNING(Service_AM, "called (STUBBED)"); |
| 244 | LogCurrentStorage(broker, "Execute"); | 244 | LogCurrentStorage(broker, "Execute"); |
| 245 | 245 | ||
| 246 | broker.PushNormalDataFromApplet(IStorage{std::vector<u8>(0x1000)}); | 246 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); |
| 247 | broker.PushInteractiveDataFromApplet(IStorage{std::vector<u8>(0x1000)}); | 247 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::vector<u8>(0x1000))); |
| 248 | broker.SignalStateChanged(); | 248 | broker.SignalStateChanged(); |
| 249 | } | 249 | } |
| 250 | 250 | ||
diff --git a/src/core/hle/service/am/applets/profile_select.cpp b/src/core/hle/service/am/applets/profile_select.cpp index 3eba696ca..70cc23552 100644 --- a/src/core/hle/service/am/applets/profile_select.cpp +++ b/src/core/hle/service/am/applets/profile_select.cpp | |||
| @@ -50,7 +50,7 @@ void ProfileSelect::ExecuteInteractive() { | |||
| 50 | 50 | ||
| 51 | void ProfileSelect::Execute() { | 51 | void ProfileSelect::Execute() { |
| 52 | if (complete) { | 52 | if (complete) { |
| 53 | broker.PushNormalDataFromApplet(IStorage{final_data}); | 53 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(final_data))); |
| 54 | return; | 54 | return; |
| 55 | } | 55 | } |
| 56 | 56 | ||
| @@ -71,7 +71,7 @@ void ProfileSelect::SelectionComplete(std::optional<Common::UUID> uuid) { | |||
| 71 | 71 | ||
| 72 | final_data = std::vector<u8>(sizeof(UserSelectionOutput)); | 72 | final_data = std::vector<u8>(sizeof(UserSelectionOutput)); |
| 73 | std::memcpy(final_data.data(), &output, final_data.size()); | 73 | std::memcpy(final_data.data(), &output, final_data.size()); |
| 74 | broker.PushNormalDataFromApplet(IStorage{final_data}); | 74 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(final_data))); |
| 75 | broker.SignalStateChanged(); | 75 | broker.SignalStateChanged(); |
| 76 | } | 76 | } |
| 77 | 77 | ||
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp index 748559cd0..54e63c138 100644 --- a/src/core/hle/service/am/applets/software_keyboard.cpp +++ b/src/core/hle/service/am/applets/software_keyboard.cpp | |||
| @@ -102,7 +102,8 @@ void SoftwareKeyboard::ExecuteInteractive() { | |||
| 102 | 102 | ||
| 103 | void SoftwareKeyboard::Execute() { | 103 | void SoftwareKeyboard::Execute() { |
| 104 | if (complete) { | 104 | if (complete) { |
| 105 | broker.PushNormalDataFromApplet(IStorage{final_data}); | 105 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(final_data))); |
| 106 | broker.SignalStateChanged(); | ||
| 106 | return; | 107 | return; |
| 107 | } | 108 | } |
| 108 | 109 | ||
| @@ -119,7 +120,7 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { | |||
| 119 | std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE); | 120 | std::vector<u8> output_sub(SWKBD_OUTPUT_BUFFER_SIZE); |
| 120 | 121 | ||
| 121 | if (config.utf_8) { | 122 | if (config.utf_8) { |
| 122 | const u64 size = text->size() + 8; | 123 | const u64 size = text->size() + sizeof(u64); |
| 123 | const auto new_text = Common::UTF16ToUTF8(*text); | 124 | const auto new_text = Common::UTF16ToUTF8(*text); |
| 124 | 125 | ||
| 125 | std::memcpy(output_sub.data(), &size, sizeof(u64)); | 126 | std::memcpy(output_sub.data(), &size, sizeof(u64)); |
| @@ -130,7 +131,7 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { | |||
| 130 | std::memcpy(output_main.data() + 4, new_text.data(), | 131 | std::memcpy(output_main.data() + 4, new_text.data(), |
| 131 | std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4)); | 132 | std::min(new_text.size(), SWKBD_OUTPUT_BUFFER_SIZE - 4)); |
| 132 | } else { | 133 | } else { |
| 133 | const u64 size = text->size() * 2 + 8; | 134 | const u64 size = text->size() * 2 + sizeof(u64); |
| 134 | std::memcpy(output_sub.data(), &size, sizeof(u64)); | 135 | std::memcpy(output_sub.data(), &size, sizeof(u64)); |
| 135 | std::memcpy(output_sub.data() + 8, text->data(), | 136 | std::memcpy(output_sub.data() + 8, text->data(), |
| 136 | std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8)); | 137 | std::min(text->size() * 2, SWKBD_OUTPUT_BUFFER_SIZE - 8)); |
| @@ -144,15 +145,15 @@ void SoftwareKeyboard::WriteText(std::optional<std::u16string> text) { | |||
| 144 | final_data = output_main; | 145 | final_data = output_main; |
| 145 | 146 | ||
| 146 | if (complete) { | 147 | if (complete) { |
| 147 | broker.PushNormalDataFromApplet(IStorage{output_main}); | 148 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(output_main))); |
| 148 | broker.SignalStateChanged(); | 149 | broker.SignalStateChanged(); |
| 149 | } else { | 150 | } else { |
| 150 | broker.PushInteractiveDataFromApplet(IStorage{output_sub}); | 151 | broker.PushInteractiveDataFromApplet(std::make_shared<IStorage>(std::move(output_sub))); |
| 151 | } | 152 | } |
| 152 | } else { | 153 | } else { |
| 153 | output_main[0] = 1; | 154 | output_main[0] = 1; |
| 154 | complete = true; | 155 | complete = true; |
| 155 | broker.PushNormalDataFromApplet(IStorage{output_main}); | 156 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(output_main))); |
| 156 | broker.SignalStateChanged(); | 157 | broker.SignalStateChanged(); |
| 157 | } | 158 | } |
| 158 | } | 159 | } |
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp index 5546ef6e8..12443c910 100644 --- a/src/core/hle/service/am/applets/web_browser.cpp +++ b/src/core/hle/service/am/applets/web_browser.cpp | |||
| @@ -284,7 +284,7 @@ void WebBrowser::Finalize() { | |||
| 284 | std::vector<u8> data(sizeof(WebCommonReturnValue)); | 284 | std::vector<u8> data(sizeof(WebCommonReturnValue)); |
| 285 | std::memcpy(data.data(), &out, sizeof(WebCommonReturnValue)); | 285 | std::memcpy(data.data(), &out, sizeof(WebCommonReturnValue)); |
| 286 | 286 | ||
| 287 | broker.PushNormalDataFromApplet(IStorage{data}); | 287 | broker.PushNormalDataFromApplet(std::make_shared<IStorage>(std::move(data))); |
| 288 | broker.SignalStateChanged(); | 288 | broker.SignalStateChanged(); |
| 289 | 289 | ||
| 290 | if (!temporary_dir.empty() && FileUtil::IsDirectory(temporary_dir)) { | 290 | if (!temporary_dir.empty() && FileUtil::IsDirectory(temporary_dir)) { |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 55d62fc5e..e6811d5b5 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -420,7 +420,7 @@ public: | |||
| 420 | return; | 420 | return; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | IFile file(result.Unwrap()); | 423 | auto file = std::make_shared<IFile>(result.Unwrap()); |
| 424 | 424 | ||
| 425 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 425 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 426 | rb.Push(RESULT_SUCCESS); | 426 | rb.Push(RESULT_SUCCESS); |
| @@ -445,7 +445,7 @@ public: | |||
| 445 | return; | 445 | return; |
| 446 | } | 446 | } |
| 447 | 447 | ||
| 448 | IDirectory directory(result.Unwrap()); | 448 | auto directory = std::make_shared<IDirectory>(result.Unwrap()); |
| 449 | 449 | ||
| 450 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 450 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 451 | rb.Push(RESULT_SUCCESS); | 451 | rb.Push(RESULT_SUCCESS); |
| @@ -794,8 +794,8 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) { | |||
| 794 | void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) { | 794 | void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) { |
| 795 | LOG_DEBUG(Service_FS, "called"); | 795 | LOG_DEBUG(Service_FS, "called"); |
| 796 | 796 | ||
| 797 | IFileSystem filesystem(fsc.OpenSDMC().Unwrap(), | 797 | auto filesystem = std::make_shared<IFileSystem>( |
| 798 | SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); | 798 | fsc.OpenSDMC().Unwrap(), SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard)); |
| 799 | 799 | ||
| 800 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 800 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 801 | rb.Push(RESULT_SUCCESS); | 801 | rb.Push(RESULT_SUCCESS); |
| @@ -846,7 +846,8 @@ void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) { | |||
| 846 | id = FileSys::StorageId::NandSystem; | 846 | id = FileSys::StorageId::NandSystem; |
| 847 | } | 847 | } |
| 848 | 848 | ||
| 849 | IFileSystem filesystem(std::move(dir.Unwrap()), SizeGetter::FromStorageId(fsc, id)); | 849 | auto filesystem = |
| 850 | std::make_shared<IFileSystem>(std::move(dir.Unwrap()), SizeGetter::FromStorageId(fsc, id)); | ||
| 850 | 851 | ||
| 851 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 852 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 852 | rb.Push(RESULT_SUCCESS); | 853 | rb.Push(RESULT_SUCCESS); |
| @@ -898,7 +899,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) { | |||
| 898 | return; | 899 | return; |
| 899 | } | 900 | } |
| 900 | 901 | ||
| 901 | IStorage storage(std::move(romfs.Unwrap())); | 902 | auto storage = std::make_shared<IStorage>(std::move(romfs.Unwrap())); |
| 902 | 903 | ||
| 903 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 904 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 904 | rb.Push(RESULT_SUCCESS); | 905 | rb.Push(RESULT_SUCCESS); |
| @@ -937,7 +938,8 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) { | |||
| 937 | 938 | ||
| 938 | FileSys::PatchManager pm{title_id}; | 939 | FileSys::PatchManager pm{title_id}; |
| 939 | 940 | ||
| 940 | IStorage storage(pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); | 941 | auto storage = std::make_shared<IStorage>( |
| 942 | pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data)); | ||
| 941 | 943 | ||
| 942 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 944 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 943 | rb.Push(RESULT_SUCCESS); | 945 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp index 5eb26caf8..8f1be0e48 100644 --- a/src/core/hle/service/prepo/prepo.cpp +++ b/src/core/hle/service/prepo/prepo.cpp | |||
| @@ -50,16 +50,16 @@ private: | |||
| 50 | IPC::RequestParser rp{ctx}; | 50 | IPC::RequestParser rp{ctx}; |
| 51 | const auto process_id = rp.PopRaw<u64>(); | 51 | const auto process_id = rp.PopRaw<u64>(); |
| 52 | 52 | ||
| 53 | const auto data1 = ctx.ReadBuffer(0); | 53 | std::vector<std::vector<u8>> data{ctx.ReadBuffer(0)}; |
| 54 | const auto data2 = ctx.ReadBuffer(1); | 54 | if (Type == Core::Reporter::PlayReportType::New) { |
| 55 | data.emplace_back(ctx.ReadBuffer(1)); | ||
| 56 | } | ||
| 55 | 57 | ||
| 56 | LOG_DEBUG(Service_PREPO, | 58 | LOG_DEBUG(Service_PREPO, "called, type={:02X}, process_id={:016X}, data1_size={:016X}", |
| 57 | "called, type={:02X}, process_id={:016X}, data1_size={:016X}, data2_size={:016X}", | 59 | static_cast<u8>(Type), process_id, data[0].size()); |
| 58 | static_cast<u8>(Type), process_id, data1.size(), data2.size()); | ||
| 59 | 60 | ||
| 60 | const auto& reporter{system.GetReporter()}; | 61 | const auto& reporter{system.GetReporter()}; |
| 61 | reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), {data1, data2}, | 62 | reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), data, process_id); |
| 62 | process_id); | ||
| 63 | 63 | ||
| 64 | IPC::ResponseBuilder rb{ctx, 2}; | 64 | IPC::ResponseBuilder rb{ctx, 2}; |
| 65 | rb.Push(RESULT_SUCCESS); | 65 | rb.Push(RESULT_SUCCESS); |
| @@ -70,19 +70,19 @@ private: | |||
| 70 | IPC::RequestParser rp{ctx}; | 70 | IPC::RequestParser rp{ctx}; |
| 71 | const auto user_id = rp.PopRaw<u128>(); | 71 | const auto user_id = rp.PopRaw<u128>(); |
| 72 | const auto process_id = rp.PopRaw<u64>(); | 72 | const auto process_id = rp.PopRaw<u64>(); |
| 73 | 73 | std::vector<std::vector<u8>> data{ctx.ReadBuffer(0)}; | |
| 74 | const auto data1 = ctx.ReadBuffer(0); | 74 | if (Type == Core::Reporter::PlayReportType::New) { |
| 75 | const auto data2 = ctx.ReadBuffer(1); | 75 | data.emplace_back(ctx.ReadBuffer(1)); |
| 76 | } | ||
| 76 | 77 | ||
| 77 | LOG_DEBUG( | 78 | LOG_DEBUG( |
| 78 | Service_PREPO, | 79 | Service_PREPO, |
| 79 | "called, type={:02X}, user_id={:016X}{:016X}, process_id={:016X}, data1_size={:016X}, " | 80 | "called, type={:02X}, user_id={:016X}{:016X}, process_id={:016X}, data1_size={:016X}", |
| 80 | "data2_size={:016X}", | 81 | static_cast<u8>(Type), user_id[1], user_id[0], process_id, data[0].size()); |
| 81 | static_cast<u8>(Type), user_id[1], user_id[0], process_id, data1.size(), data2.size()); | ||
| 82 | 82 | ||
| 83 | const auto& reporter{system.GetReporter()}; | 83 | const auto& reporter{system.GetReporter()}; |
| 84 | reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), {data1, data2}, | 84 | reporter.SavePlayReport(Type, system.CurrentProcess()->GetTitleID(), data, process_id, |
| 85 | process_id, user_id); | 85 | user_id); |
| 86 | 86 | ||
| 87 | IPC::ResponseBuilder rb{ctx, 2}; | 87 | IPC::ResponseBuilder rb{ctx, 2}; |
| 88 | rb.Push(RESULT_SUCCESS); | 88 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index ab9bbf2e7..7b1912a66 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h | |||
| @@ -704,8 +704,8 @@ public: | |||
| 704 | INSERT_UNION_PADDING_WORDS(0x15); | 704 | INSERT_UNION_PADDING_WORDS(0x15); |
| 705 | 705 | ||
| 706 | s32 stencil_back_func_ref; | 706 | s32 stencil_back_func_ref; |
| 707 | u32 stencil_back_func_mask; | ||
| 708 | u32 stencil_back_mask; | 707 | u32 stencil_back_mask; |
| 708 | u32 stencil_back_func_mask; | ||
| 709 | 709 | ||
| 710 | INSERT_UNION_PADDING_WORDS(0xC); | 710 | INSERT_UNION_PADDING_WORDS(0xC); |
| 711 | 711 | ||
| @@ -1462,8 +1462,8 @@ ASSERT_REG_POSITION(polygon_offset_fill_enable, 0x372); | |||
| 1462 | ASSERT_REG_POSITION(patch_vertices, 0x373); | 1462 | ASSERT_REG_POSITION(patch_vertices, 0x373); |
| 1463 | ASSERT_REG_POSITION(scissor_test, 0x380); | 1463 | ASSERT_REG_POSITION(scissor_test, 0x380); |
| 1464 | ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5); | 1464 | ASSERT_REG_POSITION(stencil_back_func_ref, 0x3D5); |
| 1465 | ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D6); | 1465 | ASSERT_REG_POSITION(stencil_back_mask, 0x3D6); |
| 1466 | ASSERT_REG_POSITION(stencil_back_mask, 0x3D7); | 1466 | ASSERT_REG_POSITION(stencil_back_func_mask, 0x3D7); |
| 1467 | ASSERT_REG_POSITION(color_mask_common, 0x3E4); | 1467 | ASSERT_REG_POSITION(color_mask_common, 0x3E4); |
| 1468 | ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB); | 1468 | ASSERT_REG_POSITION(rt_separate_frag_data, 0x3EB); |
| 1469 | ASSERT_REG_POSITION(depth_bounds, 0x3E7); | 1469 | ASSERT_REG_POSITION(depth_bounds, 0x3E7); |
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index cbb201114..402869fde 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -624,6 +624,19 @@ enum class ShuffleOperation : u64 { | |||
| 624 | Bfly = 3, // shuffleXorNV | 624 | Bfly = 3, // shuffleXorNV |
| 625 | }; | 625 | }; |
| 626 | 626 | ||
| 627 | enum class ShfType : u64 { | ||
| 628 | Bits32 = 0, | ||
| 629 | U64 = 2, | ||
| 630 | S64 = 3, | ||
| 631 | }; | ||
| 632 | |||
| 633 | enum class ShfXmode : u64 { | ||
| 634 | None = 0, | ||
| 635 | HI = 1, | ||
| 636 | X = 2, | ||
| 637 | XHI = 3, | ||
| 638 | }; | ||
| 639 | |||
| 627 | union Instruction { | 640 | union Instruction { |
| 628 | constexpr Instruction& operator=(const Instruction& instr) { | 641 | constexpr Instruction& operator=(const Instruction& instr) { |
| 629 | value = instr.value; | 642 | value = instr.value; |
| @@ -776,6 +789,13 @@ union Instruction { | |||
| 776 | } shr; | 789 | } shr; |
| 777 | 790 | ||
| 778 | union { | 791 | union { |
| 792 | BitField<37, 2, ShfType> type; | ||
| 793 | BitField<48, 2, ShfXmode> xmode; | ||
| 794 | BitField<50, 1, u64> wrap; | ||
| 795 | BitField<20, 6, u64> immediate; | ||
| 796 | } shf; | ||
| 797 | |||
| 798 | union { | ||
| 779 | BitField<39, 5, u64> shift_amount; | 799 | BitField<39, 5, u64> shift_amount; |
| 780 | BitField<48, 1, u64> negate_b; | 800 | BitField<48, 1, u64> negate_b; |
| 781 | BitField<49, 1, u64> negate_a; | 801 | BitField<49, 1, u64> negate_a; |
| @@ -1708,6 +1728,7 @@ public: | |||
| 1708 | BFE_C, | 1728 | BFE_C, |
| 1709 | BFE_R, | 1729 | BFE_R, |
| 1710 | BFE_IMM, | 1730 | BFE_IMM, |
| 1731 | BFI_RC, | ||
| 1711 | BFI_IMM_R, | 1732 | BFI_IMM_R, |
| 1712 | BRA, | 1733 | BRA, |
| 1713 | BRX, | 1734 | BRX, |
| @@ -2135,6 +2156,7 @@ private: | |||
| 2135 | INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"), | 2156 | INST("0100110000000---", Id::BFE_C, Type::Bfe, "BFE_C"), |
| 2136 | INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"), | 2157 | INST("0101110000000---", Id::BFE_R, Type::Bfe, "BFE_R"), |
| 2137 | INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"), | 2158 | INST("0011100-00000---", Id::BFE_IMM, Type::Bfe, "BFE_IMM"), |
| 2159 | INST("0101001111110---", Id::BFI_RC, Type::Bfi, "BFI_RC"), | ||
| 2138 | INST("0011011-11110---", Id::BFI_IMM_R, Type::Bfi, "BFI_IMM_R"), | 2160 | INST("0011011-11110---", Id::BFI_IMM_R, Type::Bfi, "BFI_IMM_R"), |
| 2139 | INST("0100110001000---", Id::LOP_C, Type::ArithmeticInteger, "LOP_C"), | 2161 | INST("0100110001000---", Id::LOP_C, Type::ArithmeticInteger, "LOP_C"), |
| 2140 | INST("0101110001000---", Id::LOP_R, Type::ArithmeticInteger, "LOP_R"), | 2162 | INST("0101110001000---", Id::LOP_R, Type::ArithmeticInteger, "LOP_R"), |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index b9c5c41a2..062ca83b8 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -23,7 +23,7 @@ MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); | |||
| 23 | GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async) | 23 | GPU::GPU(Core::System& system, VideoCore::RendererBase& renderer, bool is_async) |
| 24 | : system{system}, renderer{renderer}, is_async{is_async} { | 24 | : system{system}, renderer{renderer}, is_async{is_async} { |
| 25 | auto& rasterizer{renderer.Rasterizer()}; | 25 | auto& rasterizer{renderer.Rasterizer()}; |
| 26 | memory_manager = std::make_unique<Tegra::MemoryManager>(system, rasterizer); | 26 | memory_manager = std::make_unique<Tegra::MemoryManager>(system); |
| 27 | dma_pusher = std::make_unique<Tegra::DmaPusher>(*this); | 27 | dma_pusher = std::make_unique<Tegra::DmaPusher>(*this); |
| 28 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); | 28 | maxwell_3d = std::make_unique<Engines::Maxwell3D>(system, rasterizer, *memory_manager); |
| 29 | fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer); | 29 | fermi_2d = std::make_unique<Engines::Fermi2D>(rasterizer); |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 08dc96bb3..882e2d9c7 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
| @@ -86,7 +86,7 @@ struct CommandDataContainer { | |||
| 86 | struct SynchState final { | 86 | struct SynchState final { |
| 87 | std::atomic_bool is_running{true}; | 87 | std::atomic_bool is_running{true}; |
| 88 | 88 | ||
| 89 | using CommandQueue = Common::SPSCQueue<CommandDataContainer>; | 89 | using CommandQueue = Common::MPSCQueue<CommandDataContainer>; |
| 90 | CommandQueue queue; | 90 | CommandQueue queue; |
| 91 | u64 last_fence{}; | 91 | u64 last_fence{}; |
| 92 | std::atomic<u64> signaled_fence{}; | 92 | std::atomic<u64> signaled_fence{}; |
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 11848fbce..f1d50be3e 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -9,13 +9,12 @@ | |||
| 9 | #include "core/hle/kernel/process.h" | 9 | #include "core/hle/kernel/process.h" |
| 10 | #include "core/hle/kernel/vm_manager.h" | 10 | #include "core/hle/kernel/vm_manager.h" |
| 11 | #include "core/memory.h" | 11 | #include "core/memory.h" |
| 12 | #include "video_core/gpu.h" | ||
| 12 | #include "video_core/memory_manager.h" | 13 | #include "video_core/memory_manager.h" |
| 13 | #include "video_core/rasterizer_interface.h" | ||
| 14 | 14 | ||
| 15 | namespace Tegra { | 15 | namespace Tegra { |
| 16 | 16 | ||
| 17 | MemoryManager::MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer) | 17 | MemoryManager::MemoryManager(Core::System& system) : system{system} { |
| 18 | : rasterizer{rasterizer}, system{system} { | ||
| 19 | std::fill(page_table.pointers.begin(), page_table.pointers.end(), nullptr); | 18 | std::fill(page_table.pointers.begin(), page_table.pointers.end(), nullptr); |
| 20 | std::fill(page_table.attributes.begin(), page_table.attributes.end(), | 19 | std::fill(page_table.attributes.begin(), page_table.attributes.end(), |
| 21 | Common::PageType::Unmapped); | 20 | Common::PageType::Unmapped); |
| @@ -84,7 +83,8 @@ GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) { | |||
| 84 | const auto cpu_addr = GpuToCpuAddress(gpu_addr); | 83 | const auto cpu_addr = GpuToCpuAddress(gpu_addr); |
| 85 | ASSERT(cpu_addr); | 84 | ASSERT(cpu_addr); |
| 86 | 85 | ||
| 87 | rasterizer.FlushAndInvalidateRegion(cache_addr, aligned_size); | 86 | system.GPU().FlushAndInvalidateRegion(cache_addr, aligned_size); |
| 87 | |||
| 88 | UnmapRange(gpu_addr, aligned_size); | 88 | UnmapRange(gpu_addr, aligned_size); |
| 89 | ASSERT(system.CurrentProcess() | 89 | ASSERT(system.CurrentProcess() |
| 90 | ->VMManager() | 90 | ->VMManager() |
| @@ -242,7 +242,7 @@ void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::s | |||
| 242 | switch (page_table.attributes[page_index]) { | 242 | switch (page_table.attributes[page_index]) { |
| 243 | case Common::PageType::Memory: { | 243 | case Common::PageType::Memory: { |
| 244 | const u8* src_ptr{page_table.pointers[page_index] + page_offset}; | 244 | const u8* src_ptr{page_table.pointers[page_index] + page_offset}; |
| 245 | rasterizer.FlushRegion(ToCacheAddr(src_ptr), copy_amount); | 245 | system.GPU().FlushRegion(ToCacheAddr(src_ptr), copy_amount); |
| 246 | std::memcpy(dest_buffer, src_ptr, copy_amount); | 246 | std::memcpy(dest_buffer, src_ptr, copy_amount); |
| 247 | break; | 247 | break; |
| 248 | } | 248 | } |
| @@ -292,7 +292,7 @@ void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const | |||
| 292 | switch (page_table.attributes[page_index]) { | 292 | switch (page_table.attributes[page_index]) { |
| 293 | case Common::PageType::Memory: { | 293 | case Common::PageType::Memory: { |
| 294 | u8* dest_ptr{page_table.pointers[page_index] + page_offset}; | 294 | u8* dest_ptr{page_table.pointers[page_index] + page_offset}; |
| 295 | rasterizer.InvalidateRegion(ToCacheAddr(dest_ptr), copy_amount); | 295 | system.GPU().InvalidateRegion(ToCacheAddr(dest_ptr), copy_amount); |
| 296 | std::memcpy(dest_ptr, src_buffer, copy_amount); | 296 | std::memcpy(dest_ptr, src_buffer, copy_amount); |
| 297 | break; | 297 | break; |
| 298 | } | 298 | } |
| @@ -340,7 +340,7 @@ void MemoryManager::CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, const std:: | |||
| 340 | switch (page_table.attributes[page_index]) { | 340 | switch (page_table.attributes[page_index]) { |
| 341 | case Common::PageType::Memory: { | 341 | case Common::PageType::Memory: { |
| 342 | const u8* src_ptr{page_table.pointers[page_index] + page_offset}; | 342 | const u8* src_ptr{page_table.pointers[page_index] + page_offset}; |
| 343 | rasterizer.FlushRegion(ToCacheAddr(src_ptr), copy_amount); | 343 | system.GPU().FlushRegion(ToCacheAddr(src_ptr), copy_amount); |
| 344 | WriteBlock(dest_addr, src_ptr, copy_amount); | 344 | WriteBlock(dest_addr, src_ptr, copy_amount); |
| 345 | break; | 345 | break; |
| 346 | } | 346 | } |
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index aea010087..393447eb4 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -10,10 +10,6 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/page_table.h" | 11 | #include "common/page_table.h" |
| 12 | 12 | ||
| 13 | namespace VideoCore { | ||
| 14 | class RasterizerInterface; | ||
| 15 | } | ||
| 16 | |||
| 17 | namespace Core { | 13 | namespace Core { |
| 18 | class System; | 14 | class System; |
| 19 | } | 15 | } |
| @@ -51,7 +47,7 @@ struct VirtualMemoryArea { | |||
| 51 | 47 | ||
| 52 | class MemoryManager final { | 48 | class MemoryManager final { |
| 53 | public: | 49 | public: |
| 54 | explicit MemoryManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer); | 50 | explicit MemoryManager(Core::System& system); |
| 55 | ~MemoryManager(); | 51 | ~MemoryManager(); |
| 56 | 52 | ||
| 57 | GPUVAddr AllocateSpace(u64 size, u64 align); | 53 | GPUVAddr AllocateSpace(u64 size, u64 align); |
| @@ -176,7 +172,6 @@ private: | |||
| 176 | 172 | ||
| 177 | Common::PageTable page_table{page_bits}; | 173 | Common::PageTable page_table{page_bits}; |
| 178 | VMAMap vma_map; | 174 | VMAMap vma_map; |
| 179 | VideoCore::RasterizerInterface& rasterizer; | ||
| 180 | 175 | ||
| 181 | Core::System& system; | 176 | Core::System& system; |
| 182 | }; | 177 | }; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 0537a2abe..b0eb14c8b 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -248,9 +248,6 @@ void RasterizerOpenGL::SetupVertexInstances(GLuint vao) { | |||
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | GLintptr RasterizerOpenGL::SetupIndexBuffer() { | 250 | GLintptr RasterizerOpenGL::SetupIndexBuffer() { |
| 251 | if (accelerate_draw != AccelDraw::Indexed) { | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | MICROPROFILE_SCOPE(OpenGL_Index); | 251 | MICROPROFILE_SCOPE(OpenGL_Index); |
| 255 | const auto& regs = system.GPU().Maxwell3D().regs; | 252 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 256 | const std::size_t size = CalculateIndexBufferSize(); | 253 | const std::size_t size = CalculateIndexBufferSize(); |
| @@ -546,7 +543,8 @@ void RasterizerOpenGL::Clear() { | |||
| 546 | } | 543 | } |
| 547 | } | 544 | } |
| 548 | 545 | ||
| 549 | void RasterizerOpenGL::DrawPrelude() { | 546 | void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { |
| 547 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 550 | auto& gpu = system.GPU().Maxwell3D(); | 548 | auto& gpu = system.GPU().Maxwell3D(); |
| 551 | 549 | ||
| 552 | SyncRasterizeEnable(state); | 550 | SyncRasterizeEnable(state); |
| @@ -567,9 +565,6 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 567 | 565 | ||
| 568 | buffer_cache.Acquire(); | 566 | buffer_cache.Acquire(); |
| 569 | 567 | ||
| 570 | // Draw the vertex batch | ||
| 571 | const bool is_indexed = accelerate_draw == AccelDraw::Indexed; | ||
| 572 | |||
| 573 | std::size_t buffer_size = CalculateVertexArraysSize(); | 568 | std::size_t buffer_size = CalculateVertexArraysSize(); |
| 574 | 569 | ||
| 575 | // Add space for index buffer | 570 | // Add space for index buffer |
| @@ -596,7 +591,11 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 596 | // Upload vertex and index data. | 591 | // Upload vertex and index data. |
| 597 | SetupVertexBuffer(vao); | 592 | SetupVertexBuffer(vao); |
| 598 | SetupVertexInstances(vao); | 593 | SetupVertexInstances(vao); |
| 599 | index_buffer_offset = SetupIndexBuffer(); | 594 | |
| 595 | GLintptr index_buffer_offset; | ||
| 596 | if (is_indexed) { | ||
| 597 | index_buffer_offset = SetupIndexBuffer(); | ||
| 598 | } | ||
| 600 | 599 | ||
| 601 | // Prepare packed bindings. | 600 | // Prepare packed bindings. |
| 602 | bind_ubo_pushbuffer.Setup(); | 601 | bind_ubo_pushbuffer.Setup(); |
| @@ -630,6 +629,7 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 630 | // As all cached buffers are invalidated, we need to recheck their state. | 629 | // As all cached buffers are invalidated, we need to recheck their state. |
| 631 | gpu.dirty.ResetVertexArrays(); | 630 | gpu.dirty.ResetVertexArrays(); |
| 632 | } | 631 | } |
| 632 | gpu.dirty.memory_general = false; | ||
| 633 | 633 | ||
| 634 | shader_program_manager->ApplyTo(state); | 634 | shader_program_manager->ApplyTo(state); |
| 635 | state.Apply(); | 635 | state.Apply(); |
| @@ -637,106 +637,33 @@ void RasterizerOpenGL::DrawPrelude() { | |||
| 637 | if (texture_cache.TextureBarrier()) { | 637 | if (texture_cache.TextureBarrier()) { |
| 638 | glTextureBarrier(); | 638 | glTextureBarrier(); |
| 639 | } | 639 | } |
| 640 | } | ||
| 641 | |||
| 642 | struct DrawParams { | ||
| 643 | bool is_indexed{}; | ||
| 644 | bool is_instanced{}; | ||
| 645 | GLenum primitive_mode{}; | ||
| 646 | GLint count{}; | ||
| 647 | GLint base_vertex{}; | ||
| 648 | |||
| 649 | // Indexed settings | ||
| 650 | GLenum index_format{}; | ||
| 651 | GLintptr index_buffer_offset{}; | ||
| 652 | |||
| 653 | // Instanced setting | ||
| 654 | GLint num_instances{}; | ||
| 655 | GLint base_instance{}; | ||
| 656 | |||
| 657 | void DispatchDraw() { | ||
| 658 | if (is_indexed) { | ||
| 659 | const auto index_buffer_ptr = reinterpret_cast<const void*>(index_buffer_offset); | ||
| 660 | if (is_instanced) { | ||
| 661 | glDrawElementsInstancedBaseVertexBaseInstance(primitive_mode, count, index_format, | ||
| 662 | index_buffer_ptr, num_instances, | ||
| 663 | base_vertex, base_instance); | ||
| 664 | } else { | ||
| 665 | glDrawElementsBaseVertex(primitive_mode, count, index_format, index_buffer_ptr, | ||
| 666 | base_vertex); | ||
| 667 | } | ||
| 668 | } else { | ||
| 669 | if (is_instanced) { | ||
| 670 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, count, num_instances, | ||
| 671 | base_instance); | ||
| 672 | } else { | ||
| 673 | glDrawArrays(primitive_mode, base_vertex, count); | ||
| 674 | } | ||
| 675 | } | ||
| 676 | } | ||
| 677 | }; | ||
| 678 | |||
| 679 | bool RasterizerOpenGL::DrawBatch(bool is_indexed) { | ||
| 680 | accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; | ||
| 681 | 640 | ||
| 682 | MICROPROFILE_SCOPE(OpenGL_Drawing); | 641 | const GLuint base_instance = static_cast<GLuint>(gpu.regs.vb_base_instance); |
| 683 | 642 | const GLsizei num_instances = | |
| 684 | DrawPrelude(); | 643 | static_cast<GLsizei>(is_instanced ? gpu.mme_draw.instance_count : 1); |
| 685 | 644 | if (is_indexed) { | |
| 686 | auto& maxwell3d = system.GPU().Maxwell3D(); | 645 | const GLenum index_format = MaxwellToGL::IndexFormat(gpu.regs.index_array.format); |
| 687 | const auto& regs = maxwell3d.regs; | 646 | const GLint base_vertex = static_cast<GLint>(gpu.regs.vb_element_base); |
| 688 | const auto current_instance = maxwell3d.state.current_instance; | 647 | const GLsizei num_vertices = static_cast<GLsizei>(gpu.regs.index_array.count); |
| 689 | DrawParams draw_call{}; | 648 | glDrawElementsInstancedBaseVertexBaseInstance( |
| 690 | draw_call.is_indexed = is_indexed; | 649 | primitive_mode, num_vertices, index_format, |
| 691 | draw_call.num_instances = static_cast<GLint>(1); | 650 | reinterpret_cast<const void*>(index_buffer_offset), num_instances, base_vertex, |
| 692 | draw_call.base_instance = static_cast<GLint>(current_instance); | 651 | base_instance); |
| 693 | draw_call.is_instanced = current_instance > 0; | ||
| 694 | draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); | ||
| 695 | if (draw_call.is_indexed) { | ||
| 696 | draw_call.count = static_cast<GLint>(regs.index_array.count); | ||
| 697 | draw_call.base_vertex = static_cast<GLint>(regs.vb_element_base); | ||
| 698 | draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); | ||
| 699 | draw_call.index_buffer_offset = index_buffer_offset; | ||
| 700 | } else { | 652 | } else { |
| 701 | draw_call.count = static_cast<GLint>(regs.vertex_buffer.count); | 653 | const GLint base_vertex = static_cast<GLint>(gpu.regs.vertex_buffer.first); |
| 702 | draw_call.base_vertex = static_cast<GLint>(regs.vertex_buffer.first); | 654 | const GLsizei num_vertices = static_cast<GLsizei>(gpu.regs.vertex_buffer.count); |
| 655 | glDrawArraysInstancedBaseInstance(primitive_mode, base_vertex, num_vertices, num_instances, | ||
| 656 | base_instance); | ||
| 703 | } | 657 | } |
| 704 | draw_call.DispatchDraw(); | 658 | } |
| 705 | 659 | ||
| 706 | maxwell3d.dirty.memory_general = false; | 660 | bool RasterizerOpenGL::DrawBatch(bool is_indexed) { |
| 707 | accelerate_draw = AccelDraw::Disabled; | 661 | Draw(is_indexed, false); |
| 708 | return true; | 662 | return true; |
| 709 | } | 663 | } |
| 710 | 664 | ||
| 711 | bool RasterizerOpenGL::DrawMultiBatch(bool is_indexed) { | 665 | bool RasterizerOpenGL::DrawMultiBatch(bool is_indexed) { |
| 712 | accelerate_draw = is_indexed ? AccelDraw::Indexed : AccelDraw::Arrays; | 666 | Draw(is_indexed, true); |
| 713 | |||
| 714 | MICROPROFILE_SCOPE(OpenGL_Drawing); | ||
| 715 | |||
| 716 | DrawPrelude(); | ||
| 717 | |||
| 718 | auto& maxwell3d = system.GPU().Maxwell3D(); | ||
| 719 | const auto& regs = maxwell3d.regs; | ||
| 720 | const auto& draw_setup = maxwell3d.mme_draw; | ||
| 721 | DrawParams draw_call{}; | ||
| 722 | draw_call.is_indexed = is_indexed; | ||
| 723 | draw_call.num_instances = static_cast<GLint>(draw_setup.instance_count); | ||
| 724 | draw_call.base_instance = static_cast<GLint>(regs.vb_base_instance); | ||
| 725 | draw_call.is_instanced = draw_setup.instance_count > 1; | ||
| 726 | draw_call.primitive_mode = MaxwellToGL::PrimitiveTopology(regs.draw.topology); | ||
| 727 | if (draw_call.is_indexed) { | ||
| 728 | draw_call.count = static_cast<GLint>(regs.index_array.count); | ||
| 729 | draw_call.base_vertex = static_cast<GLint>(regs.vb_element_base); | ||
| 730 | draw_call.index_format = MaxwellToGL::IndexFormat(regs.index_array.format); | ||
| 731 | draw_call.index_buffer_offset = index_buffer_offset; | ||
| 732 | } else { | ||
| 733 | draw_call.count = static_cast<GLint>(regs.vertex_buffer.count); | ||
| 734 | draw_call.base_vertex = static_cast<GLint>(regs.vertex_buffer.first); | ||
| 735 | } | ||
| 736 | draw_call.DispatchDraw(); | ||
| 737 | |||
| 738 | maxwell3d.dirty.memory_general = false; | ||
| 739 | accelerate_draw = AccelDraw::Disabled; | ||
| 740 | return true; | 667 | return true; |
| 741 | } | 668 | } |
| 742 | 669 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 6a27cf497..0501f3828 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -103,7 +103,7 @@ private: | |||
| 103 | std::size_t size); | 103 | std::size_t size); |
| 104 | 104 | ||
| 105 | /// Syncs all the state, shaders, render targets and textures setting before a draw call. | 105 | /// Syncs all the state, shaders, render targets and textures setting before a draw call. |
| 106 | void DrawPrelude(); | 106 | void Draw(bool is_indexed, bool is_instanced); |
| 107 | 107 | ||
| 108 | /// Configures the current textures to use for the draw command. | 108 | /// Configures the current textures to use for the draw command. |
| 109 | void SetupDrawTextures(std::size_t stage_index, const Shader& shader); | 109 | void SetupDrawTextures(std::size_t stage_index, const Shader& shader); |
| @@ -220,12 +220,7 @@ private: | |||
| 220 | 220 | ||
| 221 | GLintptr SetupIndexBuffer(); | 221 | GLintptr SetupIndexBuffer(); |
| 222 | 222 | ||
| 223 | GLintptr index_buffer_offset; | ||
| 224 | |||
| 225 | void SetupShaders(GLenum primitive_mode); | 223 | void SetupShaders(GLenum primitive_mode); |
| 226 | |||
| 227 | enum class AccelDraw { Disabled, Arrays, Indexed }; | ||
| 228 | AccelDraw accelerate_draw = AccelDraw::Disabled; | ||
| 229 | }; | 224 | }; |
| 230 | 225 | ||
| 231 | } // namespace OpenGL | 226 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index ea4f35663..7ed505628 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -47,8 +47,7 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 47 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: | 47 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: |
| 48 | return GL_UNSIGNED_INT_2_10_10_10_REV; | 48 | return GL_UNSIGNED_INT_2_10_10_10_REV; |
| 49 | default: | 49 | default: |
| 50 | LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | 50 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); |
| 51 | UNREACHABLE(); | ||
| 52 | return {}; | 51 | return {}; |
| 53 | } | 52 | } |
| 54 | case Maxwell::VertexAttribute::Type::SignedInt: | 53 | case Maxwell::VertexAttribute::Type::SignedInt: |
| @@ -72,8 +71,7 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 72 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: | 71 | case Maxwell::VertexAttribute::Size::Size_10_10_10_2: |
| 73 | return GL_INT_2_10_10_10_REV; | 72 | return GL_INT_2_10_10_10_REV; |
| 74 | default: | 73 | default: |
| 75 | LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | 74 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); |
| 76 | UNREACHABLE(); | ||
| 77 | return {}; | 75 | return {}; |
| 78 | } | 76 | } |
| 79 | case Maxwell::VertexAttribute::Type::Float: | 77 | case Maxwell::VertexAttribute::Type::Float: |
| @@ -89,13 +87,19 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) { | |||
| 89 | case Maxwell::VertexAttribute::Size::Size_32_32_32_32: | 87 | case Maxwell::VertexAttribute::Size::Size_32_32_32_32: |
| 90 | return GL_FLOAT; | 88 | return GL_FLOAT; |
| 91 | default: | 89 | default: |
| 92 | LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | 90 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); |
| 93 | UNREACHABLE(); | 91 | return {}; |
| 92 | } | ||
| 93 | case Maxwell::VertexAttribute::Type::UnsignedScaled: | ||
| 94 | switch (attrib.size) { | ||
| 95 | case Maxwell::VertexAttribute::Size::Size_8_8: | ||
| 96 | return GL_UNSIGNED_BYTE; | ||
| 97 | default: | ||
| 98 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString()); | ||
| 94 | return {}; | 99 | return {}; |
| 95 | } | 100 | } |
| 96 | default: | 101 | default: |
| 97 | LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex type={}", attrib.TypeString()); | 102 | LOG_ERROR(Render_OpenGL, "Unimplemented vertex type={}", attrib.TypeString()); |
| 98 | UNREACHABLE(); | ||
| 99 | return {}; | 103 | return {}; |
| 100 | } | 104 | } |
| 101 | } | 105 | } |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index d2c6b1189..aada38702 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -571,7 +571,7 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 571 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true); | 571 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true); |
| 572 | } | 572 | } |
| 573 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { | 573 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { |
| 574 | texceptions.set(rt); | 574 | texceptions[rt] = true; |
| 575 | } | 575 | } |
| 576 | } | 576 | } |
| 577 | 577 | ||
| @@ -579,7 +579,7 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 579 | zeta_attachment = texture_cache.GetDepthBufferSurface(true); | 579 | zeta_attachment = texture_cache.GetDepthBufferSurface(true); |
| 580 | } | 580 | } |
| 581 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { | 581 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { |
| 582 | texceptions.set(ZETA_TEXCEPTION_INDEX); | 582 | texceptions[ZETA_TEXCEPTION_INDEX] = true; |
| 583 | } | 583 | } |
| 584 | 584 | ||
| 585 | texture_cache.GuardRenderTargets(false); | 585 | texture_cache.GuardRenderTargets(false); |
| @@ -1122,11 +1122,12 @@ RenderPassParams RasterizerVulkan::GetRenderPassParams(Texceptions texceptions) | |||
| 1122 | 1122 | ||
| 1123 | for (std::size_t rt = 0; rt < static_cast<std::size_t>(regs.rt_control.count); ++rt) { | 1123 | for (std::size_t rt = 0; rt < static_cast<std::size_t>(regs.rt_control.count); ++rt) { |
| 1124 | const auto& rendertarget = regs.rt[rt]; | 1124 | const auto& rendertarget = regs.rt[rt]; |
| 1125 | if (rendertarget.Address() == 0 || rendertarget.format == Tegra::RenderTargetFormat::NONE) | 1125 | if (rendertarget.Address() == 0 || rendertarget.format == Tegra::RenderTargetFormat::NONE) { |
| 1126 | continue; | 1126 | continue; |
| 1127 | } | ||
| 1127 | renderpass_params.color_attachments.push_back(RenderPassParams::ColorAttachment{ | 1128 | renderpass_params.color_attachments.push_back(RenderPassParams::ColorAttachment{ |
| 1128 | static_cast<u32>(rt), PixelFormatFromRenderTargetFormat(rendertarget.format), | 1129 | static_cast<u32>(rt), PixelFormatFromRenderTargetFormat(rendertarget.format), |
| 1129 | texceptions.test(rt)}); | 1130 | texceptions[rt]}); |
| 1130 | } | 1131 | } |
| 1131 | 1132 | ||
| 1132 | renderpass_params.has_zeta = regs.zeta_enable; | 1133 | renderpass_params.has_zeta = regs.zeta_enable; |
diff --git a/src/video_core/shader/decode/bfi.cpp b/src/video_core/shader/decode/bfi.cpp index 8be1119df..f992bbe2a 100644 --- a/src/video_core/shader/decode/bfi.cpp +++ b/src/video_core/shader/decode/bfi.cpp | |||
| @@ -17,10 +17,13 @@ u32 ShaderIR::DecodeBfi(NodeBlock& bb, u32 pc) { | |||
| 17 | const Instruction instr = {program_code[pc]}; | 17 | const Instruction instr = {program_code[pc]}; |
| 18 | const auto opcode = OpCode::Decode(instr); | 18 | const auto opcode = OpCode::Decode(instr); |
| 19 | 19 | ||
| 20 | const auto [base, packed_shift] = [&]() -> std::tuple<Node, Node> { | 20 | const auto [packed_shift, base] = [&]() -> std::pair<Node, Node> { |
| 21 | switch (opcode->get().GetId()) { | 21 | switch (opcode->get().GetId()) { |
| 22 | case OpCode::Id::BFI_RC: | ||
| 23 | return {GetRegister(instr.gpr39), | ||
| 24 | GetConstBuffer(instr.cbuf34.index, instr.cbuf34.offset)}; | ||
| 22 | case OpCode::Id::BFI_IMM_R: | 25 | case OpCode::Id::BFI_IMM_R: |
| 23 | return {GetRegister(instr.gpr39), Immediate(instr.alu.GetSignedImm20_20())}; | 26 | return {Immediate(instr.alu.GetSignedImm20_20()), GetRegister(instr.gpr39)}; |
| 24 | default: | 27 | default: |
| 25 | UNREACHABLE(); | 28 | UNREACHABLE(); |
| 26 | return {Immediate(0), Immediate(0)}; | 29 | return {Immediate(0), Immediate(0)}; |
diff --git a/src/video_core/shader/decode/shift.cpp b/src/video_core/shader/decode/shift.cpp index d419e9c45..3b391d3e6 100644 --- a/src/video_core/shader/decode/shift.cpp +++ b/src/video_core/shader/decode/shift.cpp | |||
| @@ -10,8 +10,80 @@ | |||
| 10 | 10 | ||
| 11 | namespace VideoCommon::Shader { | 11 | namespace VideoCommon::Shader { |
| 12 | 12 | ||
| 13 | using std::move; | ||
| 13 | using Tegra::Shader::Instruction; | 14 | using Tegra::Shader::Instruction; |
| 14 | using Tegra::Shader::OpCode; | 15 | using Tegra::Shader::OpCode; |
| 16 | using Tegra::Shader::ShfType; | ||
| 17 | using Tegra::Shader::ShfXmode; | ||
| 18 | |||
| 19 | namespace { | ||
| 20 | |||
| 21 | Node IsFull(Node shift) { | ||
| 22 | return Operation(OperationCode::LogicalIEqual, move(shift), Immediate(32)); | ||
| 23 | } | ||
| 24 | |||
| 25 | Node Shift(OperationCode opcode, Node value, Node shift) { | ||
| 26 | Node is_full = Operation(OperationCode::LogicalIEqual, shift, Immediate(32)); | ||
| 27 | Node shifted = Operation(opcode, move(value), shift); | ||
| 28 | return Operation(OperationCode::Select, IsFull(move(shift)), Immediate(0), move(shifted)); | ||
| 29 | } | ||
| 30 | |||
| 31 | Node ClampShift(Node shift, s32 size = 32) { | ||
| 32 | shift = Operation(OperationCode::IMax, move(shift), Immediate(0)); | ||
| 33 | return Operation(OperationCode::IMin, move(shift), Immediate(size)); | ||
| 34 | } | ||
| 35 | |||
| 36 | Node WrapShift(Node shift, s32 size = 32) { | ||
| 37 | return Operation(OperationCode::UBitwiseAnd, move(shift), Immediate(size - 1)); | ||
| 38 | } | ||
| 39 | |||
| 40 | Node ShiftRight(Node low, Node high, Node shift, Node low_shift, ShfType type) { | ||
| 41 | // These values are used when the shift value is less than 32 | ||
| 42 | Node less_low = Shift(OperationCode::ILogicalShiftRight, low, shift); | ||
| 43 | Node less_high = Shift(OperationCode::ILogicalShiftLeft, high, low_shift); | ||
| 44 | Node less = Operation(OperationCode::IBitwiseOr, move(less_high), move(less_low)); | ||
| 45 | |||
| 46 | if (type == ShfType::Bits32) { | ||
| 47 | // On 32 bit shifts we are either full (shifting 32) or shifting less than 32 bits | ||
| 48 | return Operation(OperationCode::Select, IsFull(move(shift)), move(high), move(less)); | ||
| 49 | } | ||
| 50 | |||
| 51 | // And these when it's larger than or 32 | ||
| 52 | const bool is_signed = type == ShfType::S64; | ||
| 53 | const auto opcode = SignedToUnsignedCode(OperationCode::IArithmeticShiftRight, is_signed); | ||
| 54 | Node reduced = Operation(OperationCode::IAdd, shift, Immediate(-32)); | ||
| 55 | Node greater = Shift(opcode, high, move(reduced)); | ||
| 56 | |||
| 57 | Node is_less = Operation(OperationCode::LogicalILessThan, shift, Immediate(32)); | ||
| 58 | Node is_zero = Operation(OperationCode::LogicalIEqual, move(shift), Immediate(0)); | ||
| 59 | |||
| 60 | Node value = Operation(OperationCode::Select, move(is_less), move(less), move(greater)); | ||
| 61 | return Operation(OperationCode::Select, move(is_zero), move(high), move(value)); | ||
| 62 | } | ||
| 63 | |||
| 64 | Node ShiftLeft(Node low, Node high, Node shift, Node low_shift, ShfType type) { | ||
| 65 | // These values are used when the shift value is less than 32 | ||
| 66 | Node less_low = Operation(OperationCode::ILogicalShiftRight, low, low_shift); | ||
| 67 | Node less_high = Operation(OperationCode::ILogicalShiftLeft, high, shift); | ||
| 68 | Node less = Operation(OperationCode::IBitwiseOr, move(less_low), move(less_high)); | ||
| 69 | |||
| 70 | if (type == ShfType::Bits32) { | ||
| 71 | // On 32 bit shifts we are either full (shifting 32) or shifting less than 32 bits | ||
| 72 | return Operation(OperationCode::Select, IsFull(move(shift)), move(low), move(less)); | ||
| 73 | } | ||
| 74 | |||
| 75 | // And these when it's larger than or 32 | ||
| 76 | Node reduced = Operation(OperationCode::IAdd, shift, Immediate(-32)); | ||
| 77 | Node greater = Shift(OperationCode::ILogicalShiftLeft, move(low), move(reduced)); | ||
| 78 | |||
| 79 | Node is_less = Operation(OperationCode::LogicalILessThan, shift, Immediate(32)); | ||
| 80 | Node is_zero = Operation(OperationCode::LogicalIEqual, move(shift), Immediate(0)); | ||
| 81 | |||
| 82 | Node value = Operation(OperationCode::Select, move(is_less), move(less), move(greater)); | ||
| 83 | return Operation(OperationCode::Select, move(is_zero), move(high), move(value)); | ||
| 84 | } | ||
| 85 | |||
| 86 | } // Anonymous namespace | ||
| 15 | 87 | ||
| 16 | u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) { | 88 | u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) { |
| 17 | const Instruction instr = {program_code[pc]}; | 89 | const Instruction instr = {program_code[pc]}; |
| @@ -28,29 +100,48 @@ u32 ShaderIR::DecodeShift(NodeBlock& bb, u32 pc) { | |||
| 28 | } | 100 | } |
| 29 | }(); | 101 | }(); |
| 30 | 102 | ||
| 31 | switch (opcode->get().GetId()) { | 103 | switch (const auto opid = opcode->get().GetId(); opid) { |
| 32 | case OpCode::Id::SHR_C: | 104 | case OpCode::Id::SHR_C: |
| 33 | case OpCode::Id::SHR_R: | 105 | case OpCode::Id::SHR_R: |
| 34 | case OpCode::Id::SHR_IMM: { | 106 | case OpCode::Id::SHR_IMM: { |
| 35 | if (instr.shr.wrap) { | 107 | op_b = instr.shr.wrap ? WrapShift(move(op_b)) : ClampShift(move(op_b)); |
| 36 | op_b = Operation(OperationCode::UBitwiseAnd, std::move(op_b), Immediate(0x1f)); | ||
| 37 | } else { | ||
| 38 | op_b = Operation(OperationCode::IMax, std::move(op_b), Immediate(0)); | ||
| 39 | op_b = Operation(OperationCode::IMin, std::move(op_b), Immediate(31)); | ||
| 40 | } | ||
| 41 | 108 | ||
| 42 | Node value = SignedOperation(OperationCode::IArithmeticShiftRight, instr.shift.is_signed, | 109 | Node value = SignedOperation(OperationCode::IArithmeticShiftRight, instr.shift.is_signed, |
| 43 | std::move(op_a), std::move(op_b)); | 110 | move(op_a), move(op_b)); |
| 44 | SetInternalFlagsFromInteger(bb, value, instr.generates_cc); | 111 | SetInternalFlagsFromInteger(bb, value, instr.generates_cc); |
| 45 | SetRegister(bb, instr.gpr0, std::move(value)); | 112 | SetRegister(bb, instr.gpr0, move(value)); |
| 46 | break; | 113 | break; |
| 47 | } | 114 | } |
| 48 | case OpCode::Id::SHL_C: | 115 | case OpCode::Id::SHL_C: |
| 49 | case OpCode::Id::SHL_R: | 116 | case OpCode::Id::SHL_R: |
| 50 | case OpCode::Id::SHL_IMM: { | 117 | case OpCode::Id::SHL_IMM: { |
| 51 | const Node value = Operation(OperationCode::ILogicalShiftLeft, op_a, op_b); | 118 | Node value = Operation(OperationCode::ILogicalShiftLeft, op_a, op_b); |
| 52 | SetInternalFlagsFromInteger(bb, value, instr.generates_cc); | 119 | SetInternalFlagsFromInteger(bb, value, instr.generates_cc); |
| 53 | SetRegister(bb, instr.gpr0, value); | 120 | SetRegister(bb, instr.gpr0, move(value)); |
| 121 | break; | ||
| 122 | } | ||
| 123 | case OpCode::Id::SHF_RIGHT_R: | ||
| 124 | case OpCode::Id::SHF_RIGHT_IMM: | ||
| 125 | case OpCode::Id::SHF_LEFT_R: | ||
| 126 | case OpCode::Id::SHF_LEFT_IMM: { | ||
| 127 | UNIMPLEMENTED_IF(instr.generates_cc); | ||
| 128 | UNIMPLEMENTED_IF_MSG(instr.shf.xmode != ShfXmode::None, "xmode={}", | ||
| 129 | static_cast<int>(instr.shf.xmode.Value())); | ||
| 130 | |||
| 131 | if (instr.is_b_imm) { | ||
| 132 | op_b = Immediate(static_cast<u32>(instr.shf.immediate)); | ||
| 133 | } | ||
| 134 | const s32 size = instr.shf.type == ShfType::Bits32 ? 32 : 64; | ||
| 135 | Node shift = instr.shf.wrap ? WrapShift(move(op_b), size) : ClampShift(move(op_b), size); | ||
| 136 | |||
| 137 | Node negated_shift = Operation(OperationCode::INegate, shift); | ||
| 138 | Node low_shift = Operation(OperationCode::IAdd, move(negated_shift), Immediate(32)); | ||
| 139 | |||
| 140 | const bool is_right = opid == OpCode::Id::SHF_RIGHT_R || opid == OpCode::Id::SHF_RIGHT_IMM; | ||
| 141 | Node value = (is_right ? ShiftRight : ShiftLeft)( | ||
| 142 | move(op_a), GetRegister(instr.gpr39), move(shift), move(low_shift), instr.shf.type); | ||
| 143 | |||
| 144 | SetRegister(bb, instr.gpr0, move(value)); | ||
| 54 | break; | 145 | break; |
| 55 | } | 146 | } |
| 56 | default: | 147 | default: |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 280d81ba9..cd94693c1 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -742,7 +742,6 @@ void Config::ReadUIValues() { | |||
| 742 | void Config::ReadUIGamelistValues() { | 742 | void Config::ReadUIGamelistValues() { |
| 743 | qt_config->beginGroup(QStringLiteral("UIGameList")); | 743 | qt_config->beginGroup(QStringLiteral("UIGameList")); |
| 744 | 744 | ||
| 745 | UISettings::values.show_unknown = ReadSetting(QStringLiteral("show_unknown"), true).toBool(); | ||
| 746 | UISettings::values.show_add_ons = ReadSetting(QStringLiteral("show_add_ons"), true).toBool(); | 745 | UISettings::values.show_add_ons = ReadSetting(QStringLiteral("show_add_ons"), true).toBool(); |
| 747 | UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt(); | 746 | UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt(); |
| 748 | UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt(); | 747 | UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt(); |
| @@ -1159,7 +1158,6 @@ void Config::SaveUIValues() { | |||
| 1159 | void Config::SaveUIGamelistValues() { | 1158 | void Config::SaveUIGamelistValues() { |
| 1160 | qt_config->beginGroup(QStringLiteral("UIGameList")); | 1159 | qt_config->beginGroup(QStringLiteral("UIGameList")); |
| 1161 | 1160 | ||
| 1162 | WriteSetting(QStringLiteral("show_unknown"), UISettings::values.show_unknown, true); | ||
| 1163 | WriteSetting(QStringLiteral("show_add_ons"), UISettings::values.show_add_ons, true); | 1161 | WriteSetting(QStringLiteral("show_add_ons"), UISettings::values.show_add_ons, true); |
| 1164 | WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64); | 1162 | WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64); |
| 1165 | WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3); | 1163 | WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3); |
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index c4a84cc67..94424ee44 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -40,7 +40,6 @@ ConfigureUi::ConfigureUi(QWidget* parent) : QWidget(parent), ui(new Ui::Configur | |||
| 40 | SetConfiguration(); | 40 | SetConfiguration(); |
| 41 | 41 | ||
| 42 | // Force game list reload if any of the relevant settings are changed. | 42 | // Force game list reload if any of the relevant settings are changed. |
| 43 | connect(ui->show_unknown, &QCheckBox::stateChanged, this, &ConfigureUi::RequestGameListUpdate); | ||
| 44 | connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 43 | connect(ui->icon_size_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
| 45 | &ConfigureUi::RequestGameListUpdate); | 44 | &ConfigureUi::RequestGameListUpdate); |
| 46 | connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, | 45 | connect(ui->row_1_text_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, |
| @@ -60,7 +59,6 @@ ConfigureUi::~ConfigureUi() = default; | |||
| 60 | void ConfigureUi::ApplyConfiguration() { | 59 | void ConfigureUi::ApplyConfiguration() { |
| 61 | UISettings::values.theme = | 60 | UISettings::values.theme = |
| 62 | ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); | 61 | ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString(); |
| 63 | UISettings::values.show_unknown = ui->show_unknown->isChecked(); | ||
| 64 | UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); | 62 | UISettings::values.show_add_ons = ui->show_add_ons->isChecked(); |
| 65 | UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt(); | 63 | UISettings::values.icon_size = ui->icon_size_combobox->currentData().toUInt(); |
| 66 | UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt(); | 64 | UISettings::values.row_1_text_id = ui->row_1_text_combobox->currentData().toUInt(); |
| @@ -74,7 +72,6 @@ void ConfigureUi::RequestGameListUpdate() { | |||
| 74 | 72 | ||
| 75 | void ConfigureUi::SetConfiguration() { | 73 | void ConfigureUi::SetConfiguration() { |
| 76 | ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); | 74 | ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); |
| 77 | ui->show_unknown->setChecked(UISettings::values.show_unknown); | ||
| 78 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons); | 75 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons); |
| 79 | ui->icon_size_combobox->setCurrentIndex( | 76 | ui->icon_size_combobox->setCurrentIndex( |
| 80 | ui->icon_size_combobox->findData(UISettings::values.icon_size)); | 77 | ui->icon_size_combobox->findData(UISettings::values.icon_size)); |
diff --git a/src/yuzu/configuration/configure_ui.ui b/src/yuzu/configuration/configure_ui.ui index aa36bd112..bd5c5d3c2 100644 --- a/src/yuzu/configuration/configure_ui.ui +++ b/src/yuzu/configuration/configure_ui.ui | |||
| @@ -52,13 +52,6 @@ | |||
| 52 | <item> | 52 | <item> |
| 53 | <layout class="QVBoxLayout" name="GeneralVerticalLayout"> | 53 | <layout class="QVBoxLayout" name="GeneralVerticalLayout"> |
| 54 | <item> | 54 | <item> |
| 55 | <widget class="QCheckBox" name="show_unknown"> | ||
| 56 | <property name="text"> | ||
| 57 | <string>Show files with type 'Unknown'</string> | ||
| 58 | </property> | ||
| 59 | </widget> | ||
| 60 | </item> | ||
| 61 | <item> | ||
| 62 | <widget class="QCheckBox" name="show_add_ons"> | 55 | <widget class="QCheckBox" name="show_add_ons"> |
| 63 | <property name="text"> | 56 | <property name="text"> |
| 64 | <string>Show Add-Ons Column</string> | 57 | <string>Show Add-Ons Column</string> |
diff --git a/src/yuzu/game_list_worker.cpp b/src/yuzu/game_list_worker.cpp index 4c81ef12b..da2c27aa2 100644 --- a/src/yuzu/game_list_worker.cpp +++ b/src/yuzu/game_list_worker.cpp | |||
| @@ -298,8 +298,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa | |||
| 298 | } | 298 | } |
| 299 | 299 | ||
| 300 | const auto file_type = loader->GetFileType(); | 300 | const auto file_type = loader->GetFileType(); |
| 301 | if ((file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) && | 301 | if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) { |
| 302 | !UISettings::values.show_unknown) { | ||
| 303 | return true; | 302 | return true; |
| 304 | } | 303 | } |
| 305 | 304 | ||
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index bc7725a01..a675ecf4d 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -89,7 +89,6 @@ struct Values { | |||
| 89 | int profile_index; | 89 | int profile_index; |
| 90 | 90 | ||
| 91 | // Game List | 91 | // Game List |
| 92 | bool show_unknown; | ||
| 93 | bool show_add_ons; | 92 | bool show_add_ons; |
| 94 | uint32_t icon_size; | 93 | uint32_t icon_size; |
| 95 | uint8_t row_1_text_id; | 94 | uint8_t row_1_text_id; |