diff options
33 files changed, 228 insertions, 150 deletions
diff --git a/src/common/assert.cpp b/src/common/assert.cpp index 6026b7dc2..e2c2cade3 100644 --- a/src/common/assert.cpp +++ b/src/common/assert.cpp | |||
| @@ -3,16 +3,19 @@ | |||
| 3 | 3 | ||
| 4 | #include "common/assert.h" | 4 | #include "common/assert.h" |
| 5 | #include "common/common_funcs.h" | 5 | #include "common/common_funcs.h" |
| 6 | #include "common/logging/backend.h" | ||
| 6 | 7 | ||
| 7 | #include "common/settings.h" | 8 | #include "common/settings.h" |
| 8 | 9 | ||
| 9 | void assert_fail_impl() { | 10 | void assert_fail_impl() { |
| 10 | if (Settings::values.use_debug_asserts) { | 11 | if (Settings::values.use_debug_asserts) { |
| 12 | Common::Log::Stop(); | ||
| 11 | Crash(); | 13 | Crash(); |
| 12 | } | 14 | } |
| 13 | } | 15 | } |
| 14 | 16 | ||
| 15 | [[noreturn]] void unreachable_impl() { | 17 | [[noreturn]] void unreachable_impl() { |
| 18 | Common::Log::Stop(); | ||
| 16 | Crash(); | 19 | Crash(); |
| 17 | throw std::runtime_error("Unreachable code"); | 20 | throw std::runtime_error("Unreachable code"); |
| 18 | } | 21 | } |
diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index d4f27197c..7a267f8c0 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp | |||
| @@ -208,6 +208,10 @@ public: | |||
| 208 | instance->StartBackendThread(); | 208 | instance->StartBackendThread(); |
| 209 | } | 209 | } |
| 210 | 210 | ||
| 211 | static void Stop() { | ||
| 212 | instance->StopBackendThread(); | ||
| 213 | } | ||
| 214 | |||
| 211 | Impl(const Impl&) = delete; | 215 | Impl(const Impl&) = delete; |
| 212 | Impl& operator=(const Impl&) = delete; | 216 | Impl& operator=(const Impl&) = delete; |
| 213 | 217 | ||
| @@ -259,6 +263,15 @@ private: | |||
| 259 | }); | 263 | }); |
| 260 | } | 264 | } |
| 261 | 265 | ||
| 266 | void StopBackendThread() { | ||
| 267 | backend_thread.request_stop(); | ||
| 268 | if (backend_thread.joinable()) { | ||
| 269 | backend_thread.join(); | ||
| 270 | } | ||
| 271 | |||
| 272 | ForEachBackend([](Backend& backend) { backend.Flush(); }); | ||
| 273 | } | ||
| 274 | |||
| 262 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, | 275 | Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, |
| 263 | const char* function, std::string&& message) const { | 276 | const char* function, std::string&& message) const { |
| 264 | using std::chrono::duration_cast; | 277 | using std::chrono::duration_cast; |
| @@ -313,6 +326,10 @@ void Start() { | |||
| 313 | Impl::Start(); | 326 | Impl::Start(); |
| 314 | } | 327 | } |
| 315 | 328 | ||
| 329 | void Stop() { | ||
| 330 | Impl::Stop(); | ||
| 331 | } | ||
| 332 | |||
| 316 | void DisableLoggingInTests() { | 333 | void DisableLoggingInTests() { |
| 317 | initialization_in_progress_suppress_logging = true; | 334 | initialization_in_progress_suppress_logging = true; |
| 318 | } | 335 | } |
diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index 12e5e2498..2a9926e9e 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h | |||
| @@ -14,6 +14,9 @@ void Initialize(); | |||
| 14 | 14 | ||
| 15 | void Start(); | 15 | void Start(); |
| 16 | 16 | ||
| 17 | /// Explicitly stops the logger thread and flushes the buffers | ||
| 18 | void Stop(); | ||
| 19 | |||
| 17 | void DisableLoggingInTests(); | 20 | void DisableLoggingInTests(); |
| 18 | 21 | ||
| 19 | /** | 22 | /** |
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index 5c961b202..e7e9fdb38 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h | |||
| @@ -103,7 +103,7 @@ private: | |||
| 103 | // Having them on the same cache-line would result in false-sharing between them. | 103 | // Having them on the same cache-line would result in false-sharing between them. |
| 104 | // TODO: Remove this ifdef whenever clang and GCC support | 104 | // TODO: Remove this ifdef whenever clang and GCC support |
| 105 | // std::hardware_destructive_interference_size. | 105 | // std::hardware_destructive_interference_size. |
| 106 | #if defined(_MSC_VER) && _MSC_VER >= 1911 | 106 | #ifdef __cpp_lib_hardware_interference_size |
| 107 | alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_read_index{0}; | 107 | alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_read_index{0}; |
| 108 | alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_write_index{0}; | 108 | alignas(std::hardware_destructive_interference_size) std::atomic_size_t m_write_index{0}; |
| 109 | #else | 109 | #else |
diff --git a/src/core/hle/kernel/k_auto_object_container.cpp b/src/core/hle/kernel/k_auto_object_container.cpp index 636b3f993..7bea1a1c2 100644 --- a/src/core/hle/kernel/k_auto_object_container.cpp +++ b/src/core/hle/kernel/k_auto_object_container.cpp | |||
| @@ -8,19 +8,22 @@ | |||
| 8 | namespace Kernel { | 8 | namespace Kernel { |
| 9 | 9 | ||
| 10 | void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) { | 10 | void KAutoObjectWithListContainer::Register(KAutoObjectWithList* obj) { |
| 11 | KScopedLightLock lk(m_lock); | 11 | // KScopedInterruptDisable di; |
| 12 | KScopedSpinLock lk(m_lock); | ||
| 12 | 13 | ||
| 13 | m_object_list.insert_unique(*obj); | 14 | m_object_list.insert_unique(*obj); |
| 14 | } | 15 | } |
| 15 | 16 | ||
| 16 | void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) { | 17 | void KAutoObjectWithListContainer::Unregister(KAutoObjectWithList* obj) { |
| 17 | KScopedLightLock lk(m_lock); | 18 | // KScopedInterruptDisable di; |
| 19 | KScopedSpinLock lk(m_lock); | ||
| 18 | 20 | ||
| 19 | m_object_list.erase(*obj); | 21 | m_object_list.erase(*obj); |
| 20 | } | 22 | } |
| 21 | 23 | ||
| 22 | size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) { | 24 | size_t KAutoObjectWithListContainer::GetOwnedCount(KProcess* owner) { |
| 23 | KScopedLightLock lk(m_lock); | 25 | // KScopedInterruptDisable di; |
| 26 | KScopedSpinLock lk(m_lock); | ||
| 24 | 27 | ||
| 25 | return std::count_if(m_object_list.begin(), m_object_list.end(), | 28 | return std::count_if(m_object_list.begin(), m_object_list.end(), |
| 26 | [&](const auto& obj) { return obj.GetOwner() == owner; }); | 29 | [&](const auto& obj) { return obj.GetOwner() == owner; }); |
diff --git a/src/core/hle/kernel/k_auto_object_container.h b/src/core/hle/kernel/k_auto_object_container.h index badd75d2a..770743d21 100644 --- a/src/core/hle/kernel/k_auto_object_container.h +++ b/src/core/hle/kernel/k_auto_object_container.h | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #include "common/common_funcs.h" | 8 | #include "common/common_funcs.h" |
| 9 | #include "core/hle/kernel/k_auto_object.h" | 9 | #include "core/hle/kernel/k_auto_object.h" |
| 10 | #include "core/hle/kernel/k_light_lock.h" | 10 | #include "core/hle/kernel/k_spin_lock.h" |
| 11 | 11 | ||
| 12 | namespace Kernel { | 12 | namespace Kernel { |
| 13 | 13 | ||
| @@ -21,32 +21,7 @@ public: | |||
| 21 | 21 | ||
| 22 | using ListType = boost::intrusive::rbtree<KAutoObjectWithList>; | 22 | using ListType = boost::intrusive::rbtree<KAutoObjectWithList>; |
| 23 | 23 | ||
| 24 | class ListAccessor : public KScopedLightLock { | 24 | KAutoObjectWithListContainer(KernelCore& kernel) : m_lock(), m_object_list() {} |
| 25 | public: | ||
| 26 | explicit ListAccessor(KAutoObjectWithListContainer* container) | ||
| 27 | : KScopedLightLock(container->m_lock), m_list(container->m_object_list) {} | ||
| 28 | explicit ListAccessor(KAutoObjectWithListContainer& container) | ||
| 29 | : KScopedLightLock(container.m_lock), m_list(container.m_object_list) {} | ||
| 30 | |||
| 31 | typename ListType::iterator begin() const { | ||
| 32 | return m_list.begin(); | ||
| 33 | } | ||
| 34 | |||
| 35 | typename ListType::iterator end() const { | ||
| 36 | return m_list.end(); | ||
| 37 | } | ||
| 38 | |||
| 39 | typename ListType::iterator find(typename ListType::const_reference ref) const { | ||
| 40 | return m_list.find(ref); | ||
| 41 | } | ||
| 42 | |||
| 43 | private: | ||
| 44 | ListType& m_list; | ||
| 45 | }; | ||
| 46 | |||
| 47 | friend class ListAccessor; | ||
| 48 | |||
| 49 | KAutoObjectWithListContainer(KernelCore& kernel) : m_lock(kernel), m_object_list() {} | ||
| 50 | 25 | ||
| 51 | void Initialize() {} | 26 | void Initialize() {} |
| 52 | void Finalize() {} | 27 | void Finalize() {} |
| @@ -56,7 +31,7 @@ public: | |||
| 56 | size_t GetOwnedCount(KProcess* owner); | 31 | size_t GetOwnedCount(KProcess* owner); |
| 57 | 32 | ||
| 58 | private: | 33 | private: |
| 59 | KLightLock m_lock; | 34 | KSpinLock m_lock; |
| 60 | ListType m_object_list; | 35 | ListType m_object_list; |
| 61 | }; | 36 | }; |
| 62 | 37 | ||
diff --git a/src/core/hle/kernel/k_handle_table.h b/src/core/hle/kernel/k_handle_table.h index 4e6dcd66b..1bf68e6b0 100644 --- a/src/core/hle/kernel/k_handle_table.h +++ b/src/core/hle/kernel/k_handle_table.h | |||
| @@ -30,7 +30,7 @@ public: | |||
| 30 | public: | 30 | public: |
| 31 | explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {} | 31 | explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {} |
| 32 | 32 | ||
| 33 | Result Initialize(KProcess* owner, s32 size) { | 33 | Result Initialize(s32 size) { |
| 34 | // Check that the table size is valid. | 34 | // Check that the table size is valid. |
| 35 | R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory); | 35 | R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory); |
| 36 | 36 | ||
| @@ -44,7 +44,6 @@ public: | |||
| 44 | m_next_linear_id = MinLinearId; | 44 | m_next_linear_id = MinLinearId; |
| 45 | m_count = 0; | 45 | m_count = 0; |
| 46 | m_free_head_index = -1; | 46 | m_free_head_index = -1; |
| 47 | m_owner = owner; | ||
| 48 | 47 | ||
| 49 | // Free all entries. | 48 | // Free all entries. |
| 50 | for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) { | 49 | for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) { |
| @@ -91,8 +90,7 @@ public: | |||
| 91 | // Handle pseudo-handles. | 90 | // Handle pseudo-handles. |
| 92 | if constexpr (std::derived_from<KProcess, T>) { | 91 | if constexpr (std::derived_from<KProcess, T>) { |
| 93 | if (handle == Svc::PseudoHandle::CurrentProcess) { | 92 | if (handle == Svc::PseudoHandle::CurrentProcess) { |
| 94 | // TODO: this should be the current process | 93 | auto* const cur_process = GetCurrentProcessPointer(m_kernel); |
| 95 | auto* const cur_process = m_owner; | ||
| 96 | ASSERT(cur_process != nullptr); | 94 | ASSERT(cur_process != nullptr); |
| 97 | return cur_process; | 95 | return cur_process; |
| 98 | } | 96 | } |
| @@ -302,7 +300,6 @@ private: | |||
| 302 | 300 | ||
| 303 | private: | 301 | private: |
| 304 | KernelCore& m_kernel; | 302 | KernelCore& m_kernel; |
| 305 | KProcess* m_owner{}; | ||
| 306 | std::array<EntryInfo, MaxTableSize> m_entry_infos{}; | 303 | std::array<EntryInfo, MaxTableSize> m_entry_infos{}; |
| 307 | std::array<KAutoObject*, MaxTableSize> m_objects{}; | 304 | std::array<KAutoObject*, MaxTableSize> m_objects{}; |
| 308 | mutable KSpinLock m_lock; | 305 | mutable KSpinLock m_lock; |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index b5c6867a1..53c0e3316 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -552,7 +552,7 @@ private: | |||
| 552 | 552 | ||
| 553 | Result InitializeHandleTable(s32 size) { | 553 | Result InitializeHandleTable(s32 size) { |
| 554 | // Try to initialize the handle table. | 554 | // Try to initialize the handle table. |
| 555 | R_TRY(m_handle_table.Initialize(this, size)); | 555 | R_TRY(m_handle_table.Initialize(size)); |
| 556 | 556 | ||
| 557 | // We succeeded, so note that we did. | 557 | // We succeeded, so note that we did. |
| 558 | m_is_handle_table_initialized = true; | 558 | m_is_handle_table_initialized = true; |
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp index f6ca3dc48..adaabdd6d 100644 --- a/src/core/hle/kernel/k_server_session.cpp +++ b/src/core/hle/kernel/k_server_session.cpp | |||
| @@ -1147,8 +1147,7 @@ Result KServerSession::ReceiveRequest(uintptr_t server_message, uintptr_t server | |||
| 1147 | *out_context = | 1147 | *out_context = |
| 1148 | std::make_shared<Service::HLERequestContext>(m_kernel, memory, this, client_thread); | 1148 | std::make_shared<Service::HLERequestContext>(m_kernel, memory, this, client_thread); |
| 1149 | (*out_context)->SetSessionRequestManager(manager); | 1149 | (*out_context)->SetSessionRequestManager(manager); |
| 1150 | (*out_context) | 1150 | (*out_context)->PopulateFromIncomingCommandBuffer(cmd_buf); |
| 1151 | ->PopulateFromIncomingCommandBuffer(*client_thread->GetOwnerProcess(), cmd_buf); | ||
| 1152 | // We succeeded. | 1151 | // We succeeded. |
| 1153 | R_SUCCEED(); | 1152 | R_SUCCEED(); |
| 1154 | } else { | 1153 | } else { |
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index 8a0b08761..530b45218 100644 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <optional> | 6 | #include <optional> |
| 7 | 7 | ||
| 8 | #include "core/hle/kernel/k_light_lock.h" | ||
| 8 | #include "core/hle/kernel/k_page_group.h" | 9 | #include "core/hle/kernel/k_page_group.h" |
| 9 | #include "core/hle/kernel/slab_helpers.h" | 10 | #include "core/hle/kernel/slab_helpers.h" |
| 10 | #include "core/hle/kernel/svc_types.h" | 11 | #include "core/hle/kernel/svc_types.h" |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a266d7c21..97eb56ff0 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1513,8 +1513,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) | |||
| 1513 | return; | 1513 | return; |
| 1514 | } | 1514 | } |
| 1515 | 1515 | ||
| 1516 | auto transfer_mem = | 1516 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); |
| 1517 | system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); | ||
| 1518 | 1517 | ||
| 1519 | if (transfer_mem.IsNull()) { | 1518 | if (transfer_mem.IsNull()) { |
| 1520 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | 1519 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); |
| @@ -1524,8 +1523,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(HLERequestContext& ctx) | |||
| 1524 | } | 1523 | } |
| 1525 | 1524 | ||
| 1526 | std::vector<u8> memory(transfer_mem->GetSize()); | 1525 | std::vector<u8> memory(transfer_mem->GetSize()); |
| 1527 | system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), | 1526 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); |
| 1528 | memory.size()); | ||
| 1529 | 1527 | ||
| 1530 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1528 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1531 | rb.Push(ResultSuccess); | 1529 | rb.Push(ResultSuccess); |
| @@ -1547,8 +1545,7 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { | |||
| 1547 | return; | 1545 | return; |
| 1548 | } | 1546 | } |
| 1549 | 1547 | ||
| 1550 | auto transfer_mem = | 1548 | auto transfer_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(handle); |
| 1551 | system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle); | ||
| 1552 | 1549 | ||
| 1553 | if (transfer_mem.IsNull()) { | 1550 | if (transfer_mem.IsNull()) { |
| 1554 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); | 1551 | LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle); |
| @@ -1558,8 +1555,7 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { | |||
| 1558 | } | 1555 | } |
| 1559 | 1556 | ||
| 1560 | std::vector<u8> memory(transfer_mem->GetSize()); | 1557 | std::vector<u8> memory(transfer_mem->GetSize()); |
| 1561 | system.ApplicationMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), | 1558 | ctx.GetMemory().ReadBlock(transfer_mem->GetSourceAddress(), memory.data(), memory.size()); |
| 1562 | memory.size()); | ||
| 1563 | 1559 | ||
| 1564 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 1560 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 1565 | rb.Push(ResultSuccess); | 1561 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 23e56c77a..bd4ca753b 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp | |||
| @@ -454,10 +454,8 @@ void AudRenU::OpenAudioRenderer(HLERequestContext& ctx) { | |||
| 454 | return; | 454 | return; |
| 455 | } | 455 | } |
| 456 | 456 | ||
| 457 | const auto& handle_table{system.ApplicationProcess()->GetHandleTable()}; | 457 | auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)}; |
| 458 | auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)}; | 458 | auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; |
| 459 | auto transfer_memory{ | ||
| 460 | process->GetHandleTable().GetObject<Kernel::KTransferMemory>(transfer_memory_handle)}; | ||
| 461 | 459 | ||
| 462 | const auto session_id{impl->GetSessionId()}; | 460 | const auto session_id{impl->GetSessionId()}; |
| 463 | if (session_id == -1) { | 461 | if (session_id == -1) { |
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp index 6a7bf9416..91f33aabd 100644 --- a/src/core/hle/service/audio/hwopus.cpp +++ b/src/core/hle/service/audio/hwopus.cpp | |||
| @@ -278,9 +278,7 @@ void HwOpus::OpenHardwareOpusDecoder(HLERequestContext& ctx) { | |||
| 278 | auto params = rp.PopRaw<OpusParameters>(); | 278 | auto params = rp.PopRaw<OpusParameters>(); |
| 279 | auto transfer_memory_size{rp.Pop<u32>()}; | 279 | auto transfer_memory_size{rp.Pop<u32>()}; |
| 280 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; | 280 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; |
| 281 | auto transfer_memory{ | 281 | auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; |
| 282 | system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | ||
| 283 | transfer_memory_handle)}; | ||
| 284 | 282 | ||
| 285 | LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}", | 283 | LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}", |
| 286 | params.sample_rate, params.channel_count, transfer_memory_size); | 284 | params.sample_rate, params.channel_count, transfer_memory_size); |
| @@ -323,9 +321,7 @@ void HwOpus::OpenHardwareOpusDecoderForMultiStream(HLERequestContext& ctx) { | |||
| 323 | 321 | ||
| 324 | auto transfer_memory_size{rp.Pop<u32>()}; | 322 | auto transfer_memory_size{rp.Pop<u32>()}; |
| 325 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; | 323 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; |
| 326 | auto transfer_memory{ | 324 | auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; |
| 327 | system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | ||
| 328 | transfer_memory_handle)}; | ||
| 329 | 325 | ||
| 330 | LOG_DEBUG(Service_Audio, | 326 | LOG_DEBUG(Service_Audio, |
| 331 | "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} " | 327 | "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} " |
| @@ -374,9 +370,7 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) { | |||
| 374 | auto params = rp.PopRaw<OpusParametersEx>(); | 370 | auto params = rp.PopRaw<OpusParametersEx>(); |
| 375 | auto transfer_memory_size{rp.Pop<u32>()}; | 371 | auto transfer_memory_size{rp.Pop<u32>()}; |
| 376 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; | 372 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; |
| 377 | auto transfer_memory{ | 373 | auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; |
| 378 | system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | ||
| 379 | transfer_memory_handle)}; | ||
| 380 | 374 | ||
| 381 | LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}", | 375 | LOG_DEBUG(Service_Audio, "sample_rate {} channel_count {} transfer_memory_size 0x{:X}", |
| 382 | params.sample_rate, params.channel_count, transfer_memory_size); | 376 | params.sample_rate, params.channel_count, transfer_memory_size); |
| @@ -414,9 +408,7 @@ void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) { | |||
| 414 | 408 | ||
| 415 | auto transfer_memory_size{rp.Pop<u32>()}; | 409 | auto transfer_memory_size{rp.Pop<u32>()}; |
| 416 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; | 410 | auto transfer_memory_handle{ctx.GetCopyHandle(0)}; |
| 417 | auto transfer_memory{ | 411 | auto transfer_memory{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(transfer_memory_handle)}; |
| 418 | system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | ||
| 419 | transfer_memory_handle)}; | ||
| 420 | 412 | ||
| 421 | LOG_DEBUG(Service_Audio, | 413 | LOG_DEBUG(Service_Audio, |
| 422 | "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} " | 414 | "sample_rate {} channel_count {} total_stream_count {} stereo_stream_count {} " |
diff --git a/src/core/hle/service/hid/hid_server.cpp b/src/core/hle/service/hid/hid_server.cpp index 06a01c02c..3174672af 100644 --- a/src/core/hle/service/hid/hid_server.cpp +++ b/src/core/hle/service/hid/hid_server.cpp | |||
| @@ -1850,8 +1850,7 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) { | |||
| 1850 | ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes"); | 1850 | ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes"); |
| 1851 | ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes"); | 1851 | ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes"); |
| 1852 | 1852 | ||
| 1853 | auto t_mem_1 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | 1853 | auto t_mem_1 = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_1_handle); |
| 1854 | t_mem_1_handle); | ||
| 1855 | 1854 | ||
| 1856 | if (t_mem_1.IsNull()) { | 1855 | if (t_mem_1.IsNull()) { |
| 1857 | LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle); | 1856 | LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle); |
| @@ -1860,8 +1859,7 @@ void IHidServer::InitializeSevenSixAxisSensor(HLERequestContext& ctx) { | |||
| 1860 | return; | 1859 | return; |
| 1861 | } | 1860 | } |
| 1862 | 1861 | ||
| 1863 | auto t_mem_2 = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | 1862 | auto t_mem_2 = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_2_handle); |
| 1864 | t_mem_2_handle); | ||
| 1865 | 1863 | ||
| 1866 | if (t_mem_2.IsNull()) { | 1864 | if (t_mem_2.IsNull()) { |
| 1867 | LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle); | 1865 | LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle); |
| @@ -2142,8 +2140,7 @@ void IHidServer::WritePalmaWaveEntry(HLERequestContext& ctx) { | |||
| 2142 | 2140 | ||
| 2143 | ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes"); | 2141 | ASSERT_MSG(t_mem_size == 0x3000, "t_mem_size is not 0x3000 bytes"); |
| 2144 | 2142 | ||
| 2145 | auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | 2143 | auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); |
| 2146 | t_mem_handle); | ||
| 2147 | 2144 | ||
| 2148 | if (t_mem.IsNull()) { | 2145 | if (t_mem.IsNull()) { |
| 2149 | LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); | 2146 | LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); |
diff --git a/src/core/hle/service/hid/hidbus.cpp b/src/core/hle/service/hid/hidbus.cpp index 80aac221b..d12f9beb0 100644 --- a/src/core/hle/service/hid/hidbus.cpp +++ b/src/core/hle/service/hid/hidbus.cpp | |||
| @@ -448,8 +448,7 @@ void HidBus::EnableJoyPollingReceiveMode(HLERequestContext& ctx) { | |||
| 448 | 448 | ||
| 449 | ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes"); | 449 | ASSERT_MSG(t_mem_size == 0x1000, "t_mem_size is not 0x1000 bytes"); |
| 450 | 450 | ||
| 451 | auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | 451 | auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); |
| 452 | t_mem_handle); | ||
| 453 | 452 | ||
| 454 | if (t_mem.IsNull()) { | 453 | if (t_mem.IsNull()) { |
| 455 | LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); | 454 | LOG_ERROR(Service_HID, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); |
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index 39b9a4474..008debfd1 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp | |||
| @@ -197,8 +197,7 @@ void IRS::RunImageTransferProcessor(HLERequestContext& ctx) { | |||
| 197 | const auto parameters{rp.PopRaw<Parameters>()}; | 197 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 198 | const auto t_mem_handle{ctx.GetCopyHandle(0)}; | 198 | const auto t_mem_handle{ctx.GetCopyHandle(0)}; |
| 199 | 199 | ||
| 200 | auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | 200 | auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); |
| 201 | t_mem_handle); | ||
| 202 | 201 | ||
| 203 | if (t_mem.IsNull()) { | 202 | if (t_mem.IsNull()) { |
| 204 | LOG_ERROR(Service_IRS, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); | 203 | LOG_ERROR(Service_IRS, "t_mem is a nullptr for handle=0x{:08X}", t_mem_handle); |
| @@ -444,8 +443,7 @@ void IRS::RunImageTransferExProcessor(HLERequestContext& ctx) { | |||
| 444 | const auto parameters{rp.PopRaw<Parameters>()}; | 443 | const auto parameters{rp.PopRaw<Parameters>()}; |
| 445 | const auto t_mem_handle{ctx.GetCopyHandle(0)}; | 444 | const auto t_mem_handle{ctx.GetCopyHandle(0)}; |
| 446 | 445 | ||
| 447 | auto t_mem = system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>( | 446 | auto t_mem = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(t_mem_handle); |
| 448 | t_mem_handle); | ||
| 449 | 447 | ||
| 450 | LOG_INFO(Service_IRS, | 448 | LOG_INFO(Service_IRS, |
| 451 | "called, npad_type={}, npad_id={}, transfer_memory_size={}, " | 449 | "called, npad_type={}, npad_id={}, transfer_memory_size={}, " |
diff --git a/src/core/hle/service/hle_ipc.cpp b/src/core/hle/service/hle_ipc.cpp index 38955932c..39df77e43 100644 --- a/src/core/hle/service/hle_ipc.cpp +++ b/src/core/hle/service/hle_ipc.cpp | |||
| @@ -146,10 +146,7 @@ HLERequestContext::HLERequestContext(Kernel::KernelCore& kernel_, Core::Memory:: | |||
| 146 | 146 | ||
| 147 | HLERequestContext::~HLERequestContext() = default; | 147 | HLERequestContext::~HLERequestContext() = default; |
| 148 | 148 | ||
| 149 | void HLERequestContext::ParseCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf, | 149 | void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { |
| 150 | bool incoming) { | ||
| 151 | client_handle_table = &process.GetHandleTable(); | ||
| 152 | |||
| 153 | IPC::RequestParser rp(src_cmdbuf); | 150 | IPC::RequestParser rp(src_cmdbuf); |
| 154 | command_header = rp.PopRaw<IPC::CommandHeader>(); | 151 | command_header = rp.PopRaw<IPC::CommandHeader>(); |
| 155 | 152 | ||
| @@ -162,7 +159,7 @@ void HLERequestContext::ParseCommandBuffer(Kernel::KProcess& process, u32_le* sr | |||
| 162 | if (command_header->enable_handle_descriptor) { | 159 | if (command_header->enable_handle_descriptor) { |
| 163 | handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); | 160 | handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); |
| 164 | if (handle_descriptor_header->send_current_pid) { | 161 | if (handle_descriptor_header->send_current_pid) { |
| 165 | pid = process.GetProcessId(); | 162 | pid = thread->GetOwnerProcess()->GetProcessId(); |
| 166 | rp.Skip(2, false); | 163 | rp.Skip(2, false); |
| 167 | } | 164 | } |
| 168 | if (incoming) { | 165 | if (incoming) { |
| @@ -270,9 +267,10 @@ void HLERequestContext::ParseCommandBuffer(Kernel::KProcess& process, u32_le* sr | |||
| 270 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. | 267 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. |
| 271 | } | 268 | } |
| 272 | 269 | ||
| 273 | Result HLERequestContext::PopulateFromIncomingCommandBuffer(Kernel::KProcess& process, | 270 | Result HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf) { |
| 274 | u32_le* src_cmdbuf) { | 271 | client_handle_table = &thread->GetOwnerProcess()->GetHandleTable(); |
| 275 | ParseCommandBuffer(process, src_cmdbuf, true); | 272 | |
| 273 | ParseCommandBuffer(src_cmdbuf, true); | ||
| 276 | 274 | ||
| 277 | if (command_header->IsCloseCommand()) { | 275 | if (command_header->IsCloseCommand()) { |
| 278 | // Close does not populate the rest of the IPC header | 276 | // Close does not populate the rest of the IPC header |
| @@ -284,9 +282,9 @@ Result HLERequestContext::PopulateFromIncomingCommandBuffer(Kernel::KProcess& pr | |||
| 284 | return ResultSuccess; | 282 | return ResultSuccess; |
| 285 | } | 283 | } |
| 286 | 284 | ||
| 287 | Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesting_thread) { | 285 | Result HLERequestContext::WriteToOutgoingCommandBuffer() { |
| 288 | auto current_offset = handles_offset; | 286 | auto current_offset = handles_offset; |
| 289 | auto& owner_process = *requesting_thread.GetOwnerProcess(); | 287 | auto& owner_process = *thread->GetOwnerProcess(); |
| 290 | auto& handle_table = owner_process.GetHandleTable(); | 288 | auto& handle_table = owner_process.GetHandleTable(); |
| 291 | 289 | ||
| 292 | for (auto& object : outgoing_copy_objects) { | 290 | for (auto& object : outgoing_copy_objects) { |
| @@ -319,7 +317,7 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer(Kernel::KThread& requesti | |||
| 319 | } | 317 | } |
| 320 | 318 | ||
| 321 | // Copy the translated command buffer back into the thread's command buffer area. | 319 | // Copy the translated command buffer back into the thread's command buffer area. |
| 322 | memory.WriteBlock(requesting_thread.GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32)); | 320 | memory.WriteBlock(thread->GetTlsAddress(), cmd_buf.data(), write_size * sizeof(u32)); |
| 323 | 321 | ||
| 324 | return ResultSuccess; | 322 | return ResultSuccess; |
| 325 | } | 323 | } |
diff --git a/src/core/hle/service/hle_ipc.h b/src/core/hle/service/hle_ipc.h index 18d464c63..40d86943e 100644 --- a/src/core/hle/service/hle_ipc.h +++ b/src/core/hle/service/hle_ipc.h | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "common/concepts.h" | 17 | #include "common/concepts.h" |
| 18 | #include "common/swap.h" | 18 | #include "common/swap.h" |
| 19 | #include "core/hle/ipc.h" | 19 | #include "core/hle/ipc.h" |
| 20 | #include "core/hle/kernel/k_handle_table.h" | ||
| 20 | #include "core/hle/kernel/svc_common.h" | 21 | #include "core/hle/kernel/svc_common.h" |
| 21 | 22 | ||
| 22 | union Result; | 23 | union Result; |
| @@ -196,10 +197,10 @@ public: | |||
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | /// Populates this context with data from the requesting process/thread. | 199 | /// Populates this context with data from the requesting process/thread. |
| 199 | Result PopulateFromIncomingCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf); | 200 | Result PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf); |
| 200 | 201 | ||
| 201 | /// Writes data from this context back to the requesting process/thread. | 202 | /// Writes data from this context back to the requesting process/thread. |
| 202 | Result WriteToOutgoingCommandBuffer(Kernel::KThread& requesting_thread); | 203 | Result WriteToOutgoingCommandBuffer(); |
| 203 | 204 | ||
| 204 | [[nodiscard]] u32_le GetHipcCommand() const { | 205 | [[nodiscard]] u32_le GetHipcCommand() const { |
| 205 | return command; | 206 | return command; |
| @@ -359,8 +360,17 @@ public: | |||
| 359 | return *thread; | 360 | return *thread; |
| 360 | } | 361 | } |
| 361 | 362 | ||
| 362 | Kernel::KHandleTable& GetClientHandleTable() { | 363 | [[nodiscard]] Core::Memory::Memory& GetMemory() const { |
| 363 | return *client_handle_table; | 364 | return memory; |
| 365 | } | ||
| 366 | |||
| 367 | template <typename T> | ||
| 368 | Kernel::KScopedAutoObject<T> GetObjectFromHandle(u32 handle) { | ||
| 369 | auto obj = client_handle_table->GetObjectForIpc(handle, thread); | ||
| 370 | if (obj.IsNotNull()) { | ||
| 371 | return obj->DynamicCast<T*>(); | ||
| 372 | } | ||
| 373 | return nullptr; | ||
| 364 | } | 374 | } |
| 365 | 375 | ||
| 366 | [[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const { | 376 | [[nodiscard]] std::shared_ptr<SessionRequestManager> GetManager() const { |
| @@ -378,7 +388,7 @@ public: | |||
| 378 | private: | 388 | private: |
| 379 | friend class IPC::ResponseBuilder; | 389 | friend class IPC::ResponseBuilder; |
| 380 | 390 | ||
| 381 | void ParseCommandBuffer(Kernel::KProcess& process, u32_le* src_cmdbuf, bool incoming); | 391 | void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming); |
| 382 | 392 | ||
| 383 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; | 393 | std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; |
| 384 | Kernel::KServerSession* server_session{}; | 394 | Kernel::KServerSession* server_session{}; |
diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 65851fc05..a94d05e19 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp | |||
| @@ -26,7 +26,7 @@ public: | |||
| 26 | explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx, | 26 | explicit IJitEnvironment(Core::System& system_, Kernel::KProcess& process_, CodeRange user_rx, |
| 27 | CodeRange user_ro) | 27 | CodeRange user_ro) |
| 28 | : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, | 28 | : ServiceFramework{system_, "IJitEnvironment"}, process{&process_}, |
| 29 | context{system_.ApplicationMemory()} { | 29 | context{process->GetMemory()} { |
| 30 | // clang-format off | 30 | // clang-format off |
| 31 | static const FunctionInfo functions[] = { | 31 | static const FunctionInfo functions[] = { |
| 32 | {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, | 32 | {0, &IJitEnvironment::GenerateCode, "GenerateCode"}, |
| @@ -188,7 +188,7 @@ public: | |||
| 188 | return; | 188 | return; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | auto tmem{process->GetHandleTable().GetObject<Kernel::KTransferMemory>(tmem_handle)}; | 191 | auto tmem{ctx.GetObjectFromHandle<Kernel::KTransferMemory>(tmem_handle)}; |
| 192 | if (tmem.IsNull()) { | 192 | if (tmem.IsNull()) { |
| 193 | LOG_ERROR(Service_JIT, "attempted to load plugin with invalid transfer memory handle"); | 193 | LOG_ERROR(Service_JIT, "attempted to load plugin with invalid transfer memory handle"); |
| 194 | IPC::ResponseBuilder rb{ctx, 2}; | 194 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -356,11 +356,7 @@ public: | |||
| 356 | return; | 356 | return; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | // Fetch using the handle table for the application process here, | 359 | auto process{ctx.GetObjectFromHandle<Kernel::KProcess>(process_handle)}; |
| 360 | // since we are not multiprocess yet. | ||
| 361 | const auto& handle_table{system.ApplicationProcess()->GetHandleTable()}; | ||
| 362 | |||
| 363 | auto process{handle_table.GetObject<Kernel::KProcess>(process_handle)}; | ||
| 364 | if (process.IsNull()) { | 360 | if (process.IsNull()) { |
| 365 | LOG_ERROR(Service_JIT, "process is null for handle=0x{:08X}", process_handle); | 361 | LOG_ERROR(Service_JIT, "process is null for handle=0x{:08X}", process_handle); |
| 366 | IPC::ResponseBuilder rb{ctx, 2}; | 362 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -368,7 +364,7 @@ public: | |||
| 368 | return; | 364 | return; |
| 369 | } | 365 | } |
| 370 | 366 | ||
| 371 | auto rx_mem{handle_table.GetObject<Kernel::KCodeMemory>(rx_mem_handle)}; | 367 | auto rx_mem{ctx.GetObjectFromHandle<Kernel::KCodeMemory>(rx_mem_handle)}; |
| 372 | if (rx_mem.IsNull()) { | 368 | if (rx_mem.IsNull()) { |
| 373 | LOG_ERROR(Service_JIT, "rx_mem is null for handle=0x{:08X}", rx_mem_handle); | 369 | LOG_ERROR(Service_JIT, "rx_mem is null for handle=0x{:08X}", rx_mem_handle); |
| 374 | IPC::ResponseBuilder rb{ctx, 2}; | 370 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -376,7 +372,7 @@ public: | |||
| 376 | return; | 372 | return; |
| 377 | } | 373 | } |
| 378 | 374 | ||
| 379 | auto ro_mem{handle_table.GetObject<Kernel::KCodeMemory>(ro_mem_handle)}; | 375 | auto ro_mem{ctx.GetObjectFromHandle<Kernel::KCodeMemory>(ro_mem_handle)}; |
| 380 | if (ro_mem.IsNull()) { | 376 | if (ro_mem.IsNull()) { |
| 381 | LOG_ERROR(Service_JIT, "ro_mem is null for handle=0x{:08X}", ro_mem_handle); | 377 | LOG_ERROR(Service_JIT, "ro_mem is null for handle=0x{:08X}", ro_mem_handle); |
| 382 | IPC::ResponseBuilder rb{ctx, 2}; | 378 | IPC::ResponseBuilder rb{ctx, 2}; |
diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp index 17110d3f1..f0658bb5d 100644 --- a/src/core/hle/service/ro/ro.cpp +++ b/src/core/hle/service/ro/ro.cpp | |||
| @@ -651,10 +651,9 @@ private: | |||
| 651 | void RegisterProcessHandle(HLERequestContext& ctx) { | 651 | void RegisterProcessHandle(HLERequestContext& ctx) { |
| 652 | LOG_DEBUG(Service_LDR, "(called)"); | 652 | LOG_DEBUG(Service_LDR, "(called)"); |
| 653 | 653 | ||
| 654 | auto process_h = ctx.GetClientHandleTable().GetObject(ctx.GetCopyHandle(0)); | 654 | auto process = ctx.GetObjectFromHandle<Kernel::KProcess>(ctx.GetCopyHandle(0)); |
| 655 | auto client_pid = ctx.GetPID(); | 655 | auto client_pid = ctx.GetPID(); |
| 656 | auto result = interface.RegisterProcessHandle(client_pid, | 656 | auto result = interface.RegisterProcessHandle(client_pid, process.GetPointerUnsafe()); |
| 657 | process_h->DynamicCast<Kernel::KProcess*>()); | ||
| 658 | 657 | ||
| 659 | IPC::ResponseBuilder rb{ctx, 2}; | 658 | IPC::ResponseBuilder rb{ctx, 2}; |
| 660 | rb.Push(result); | 659 | rb.Push(result); |
| @@ -671,12 +670,11 @@ private: | |||
| 671 | 670 | ||
| 672 | IPC::RequestParser rp{ctx}; | 671 | IPC::RequestParser rp{ctx}; |
| 673 | auto params = rp.PopRaw<InputParameters>(); | 672 | auto params = rp.PopRaw<InputParameters>(); |
| 674 | auto process_h = ctx.GetClientHandleTable().GetObject(ctx.GetCopyHandle(0)); | 673 | auto process = ctx.GetObjectFromHandle<Kernel::KProcess>(ctx.GetCopyHandle(0)); |
| 675 | 674 | ||
| 676 | auto client_pid = ctx.GetPID(); | 675 | auto client_pid = ctx.GetPID(); |
| 677 | auto result = | 676 | auto result = interface.RegisterProcessModuleInfo( |
| 678 | interface.RegisterProcessModuleInfo(client_pid, params.nrr_address, params.nrr_size, | 677 | client_pid, params.nrr_address, params.nrr_size, process.GetPointerUnsafe()); |
| 679 | process_h->DynamicCast<Kernel::KProcess*>()); | ||
| 680 | 678 | ||
| 681 | IPC::ResponseBuilder rb{ctx, 2}; | 679 | IPC::ResponseBuilder rb{ctx, 2}; |
| 682 | rb.Push(result); | 680 | rb.Push(result); |
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 00531b021..39124c5fd 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp | |||
| @@ -203,7 +203,7 @@ Result ServiceFrameworkBase::HandleSyncRequest(Kernel::KServerSession& session, | |||
| 203 | // If emulation was shutdown, we are closing service threads, do not write the response back to | 203 | // If emulation was shutdown, we are closing service threads, do not write the response back to |
| 204 | // memory that may be shutting down as well. | 204 | // memory that may be shutting down as well. |
| 205 | if (system.IsPoweredOn()) { | 205 | if (system.IsPoweredOn()) { |
| 206 | ctx.WriteToOutgoingCommandBuffer(ctx.GetThread()); | 206 | ctx.WriteToOutgoingCommandBuffer(); |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | return result; | 209 | return result; |
diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index ed023fcfe..89ebab08e 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp | |||
| @@ -96,9 +96,9 @@ Id ImageType(EmitContext& ctx, const ImageDescriptor& desc, Id sampled_type) { | |||
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, | 98 | Id DefineVariable(EmitContext& ctx, Id type, std::optional<spv::BuiltIn> builtin, |
| 99 | spv::StorageClass storage_class) { | 99 | spv::StorageClass storage_class, std::optional<Id> initializer = std::nullopt) { |
| 100 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; | 100 | const Id pointer_type{ctx.TypePointer(storage_class, type)}; |
| 101 | const Id id{ctx.AddGlobalVariable(pointer_type, storage_class)}; | 101 | const Id id{ctx.AddGlobalVariable(pointer_type, storage_class, initializer)}; |
| 102 | if (builtin) { | 102 | if (builtin) { |
| 103 | ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin); | 103 | ctx.Decorate(id, spv::Decoration::BuiltIn, *builtin); |
| 104 | } | 104 | } |
| @@ -144,11 +144,12 @@ Id DefineInput(EmitContext& ctx, Id type, bool per_invocation, | |||
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, | 146 | Id DefineOutput(EmitContext& ctx, Id type, std::optional<u32> invocations, |
| 147 | std::optional<spv::BuiltIn> builtin = std::nullopt) { | 147 | std::optional<spv::BuiltIn> builtin = std::nullopt, |
| 148 | std::optional<Id> initializer = std::nullopt) { | ||
| 148 | if (invocations && ctx.stage == Stage::TessellationControl) { | 149 | if (invocations && ctx.stage == Stage::TessellationControl) { |
| 149 | type = ctx.TypeArray(type, ctx.Const(*invocations)); | 150 | type = ctx.TypeArray(type, ctx.Const(*invocations)); |
| 150 | } | 151 | } |
| 151 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output); | 152 | return DefineVariable(ctx, type, builtin, spv::StorageClass::Output, initializer); |
| 152 | } | 153 | } |
| 153 | 154 | ||
| 154 | void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invocations) { | 155 | void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invocations) { |
| @@ -811,10 +812,14 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 811 | labels.push_back(OpLabel()); | 812 | labels.push_back(OpLabel()); |
| 812 | } | 813 | } |
| 813 | if (info.stores.ClipDistances()) { | 814 | if (info.stores.ClipDistances()) { |
| 814 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2); | 815 | if (profile.max_user_clip_distances >= 4) { |
| 815 | labels.push_back(OpLabel()); | 816 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance0) >> 2); |
| 816 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2); | 817 | labels.push_back(OpLabel()); |
| 817 | labels.push_back(OpLabel()); | 818 | } |
| 819 | if (profile.max_user_clip_distances >= 8) { | ||
| 820 | literals.push_back(static_cast<u32>(IR::Attribute::ClipDistance4) >> 2); | ||
| 821 | labels.push_back(OpLabel()); | ||
| 822 | } | ||
| 818 | } | 823 | } |
| 819 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); | 824 | OpSelectionMerge(end_block, spv::SelectionControlMask::MaskNone); |
| 820 | OpSwitch(compare_index, default_label, literals, labels); | 825 | OpSwitch(compare_index, default_label, literals, labels); |
| @@ -843,17 +848,21 @@ void EmitContext::DefineAttributeMemAccess(const Info& info) { | |||
| 843 | ++label_index; | 848 | ++label_index; |
| 844 | } | 849 | } |
| 845 | if (info.stores.ClipDistances()) { | 850 | if (info.stores.ClipDistances()) { |
| 846 | AddLabel(labels[label_index]); | 851 | if (profile.max_user_clip_distances >= 4) { |
| 847 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; | 852 | AddLabel(labels[label_index]); |
| 848 | OpStore(pointer, store_value); | 853 | const Id pointer{OpAccessChain(output_f32, clip_distances, masked_index)}; |
| 849 | OpReturn(); | 854 | OpStore(pointer, store_value); |
| 850 | ++label_index; | 855 | OpReturn(); |
| 851 | AddLabel(labels[label_index]); | 856 | ++label_index; |
| 852 | const Id fixed_index{OpIAdd(U32[1], masked_index, Const(4U))}; | 857 | } |
| 853 | const Id pointer2{OpAccessChain(output_f32, clip_distances, fixed_index)}; | 858 | if (profile.max_user_clip_distances >= 8) { |
| 854 | OpStore(pointer2, store_value); | 859 | AddLabel(labels[label_index]); |
| 855 | OpReturn(); | 860 | const Id fixed_index{OpIAdd(U32[1], masked_index, Const(4U))}; |
| 856 | ++label_index; | 861 | const Id pointer{OpAccessChain(output_f32, clip_distances, fixed_index)}; |
| 862 | OpStore(pointer, store_value); | ||
| 863 | OpReturn(); | ||
| 864 | ++label_index; | ||
| 865 | } | ||
| 857 | } | 866 | } |
| 858 | AddLabel(end_block); | 867 | AddLabel(end_block); |
| 859 | OpUnreachable(); | 868 | OpUnreachable(); |
| @@ -1532,9 +1541,16 @@ void EmitContext::DefineOutputs(const IR::Program& program) { | |||
| 1532 | if (stage == Stage::Fragment) { | 1541 | if (stage == Stage::Fragment) { |
| 1533 | throw NotImplementedException("Storing ClipDistance in fragment stage"); | 1542 | throw NotImplementedException("Storing ClipDistance in fragment stage"); |
| 1534 | } | 1543 | } |
| 1535 | const Id type{TypeArray( | 1544 | if (profile.max_user_clip_distances > 0) { |
| 1536 | F32[1], Const(std::min(info.used_clip_distances, profile.max_user_clip_distances)))}; | 1545 | const u32 used{std::min(profile.max_user_clip_distances, 8u)}; |
| 1537 | clip_distances = DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance); | 1546 | const std::array<Id, 8> zero{f32_zero_value, f32_zero_value, f32_zero_value, |
| 1547 | f32_zero_value, f32_zero_value, f32_zero_value, | ||
| 1548 | f32_zero_value, f32_zero_value}; | ||
| 1549 | const Id type{TypeArray(F32[1], Const(used))}; | ||
| 1550 | const Id initializer{ConstantComposite(type, std::span(zero).subspan(0, used))}; | ||
| 1551 | clip_distances = | ||
| 1552 | DefineOutput(*this, type, invocations, spv::BuiltIn::ClipDistance, initializer); | ||
| 1553 | } | ||
| 1538 | } | 1554 | } |
| 1539 | if (info.stores[IR::Attribute::Layer] && | 1555 | if (info.stores[IR::Attribute::Layer] && |
| 1540 | (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { | 1556 | (profile.support_viewport_index_layer_non_geometry || stage == Stage::Geometry)) { |
diff --git a/src/video_core/macro/macro_hle.cpp b/src/video_core/macro/macro_hle.cpp index 046c8085e..46e853e04 100644 --- a/src/video_core/macro/macro_hle.cpp +++ b/src/video_core/macro/macro_hle.cpp | |||
| @@ -327,12 +327,13 @@ public: | |||
| 327 | explicit HLE_DrawIndirectByteCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} | 327 | explicit HLE_DrawIndirectByteCount(Maxwell3D& maxwell3d_) : HLEMacroImpl(maxwell3d_) {} |
| 328 | 328 | ||
| 329 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { | 329 | void Execute(const std::vector<u32>& parameters, [[maybe_unused]] u32 method) override { |
| 330 | const bool force = maxwell3d.Rasterizer().HasDrawTransformFeedback(); | ||
| 331 | |||
| 330 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0xFFFFU); | 332 | auto topology = static_cast<Maxwell3D::Regs::PrimitiveTopology>(parameters[0] & 0xFFFFU); |
| 331 | if (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology)) { | 333 | if (!force && (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology))) { |
| 332 | Fallback(parameters); | 334 | Fallback(parameters); |
| 333 | return; | 335 | return; |
| 334 | } | 336 | } |
| 335 | |||
| 336 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); | 337 | auto& params = maxwell3d.draw_manager->GetIndirectParams(); |
| 337 | params.is_byte_count = true; | 338 | params.is_byte_count = true; |
| 338 | params.is_indexed = false; | 339 | params.is_indexed = false; |
| @@ -503,6 +504,8 @@ public: | |||
| 503 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); | 504 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(launch_dma)), 0x1011, true); |
| 504 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)), | 505 | maxwell3d.CallMethod(static_cast<size_t>(MAXWELL3D_REG_INDEX(inline_data)), |
| 505 | regs.transform_feedback.controls[0].stride, true); | 506 | regs.transform_feedback.controls[0].stride, true); |
| 507 | |||
| 508 | maxwell3d.Rasterizer().RegisterTransformFeedback(regs.upload.dest.Address()); | ||
| 506 | } | 509 | } |
| 507 | }; | 510 | }; |
| 508 | 511 | ||
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index af1469147..49224ca85 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -173,5 +173,13 @@ public: | |||
| 173 | virtual void BindChannel(Tegra::Control::ChannelState& channel) {} | 173 | virtual void BindChannel(Tegra::Control::ChannelState& channel) {} |
| 174 | 174 | ||
| 175 | virtual void ReleaseChannel(s32 channel_id) {} | 175 | virtual void ReleaseChannel(s32 channel_id) {} |
| 176 | |||
| 177 | /// Register the address as a Transform Feedback Object | ||
| 178 | virtual void RegisterTransformFeedback(GPUVAddr tfb_object_addr) {} | ||
| 179 | |||
| 180 | /// Returns true when the rasterizer has Draw Transform Feedback capabilities | ||
| 181 | virtual bool HasDrawTransformFeedback() { | ||
| 182 | return false; | ||
| 183 | } | ||
| 176 | }; | 184 | }; |
| 177 | } // namespace VideoCore | 185 | } // namespace VideoCore |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index b787b6994..517ac14dd 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -376,4 +376,15 @@ void BufferCacheRuntime::BindImageBuffer(Buffer& buffer, u32 offset, u32 size, P | |||
| 376 | *image_handles++ = buffer.View(offset, size, format); | 376 | *image_handles++ = buffer.View(offset, size, format); |
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | void BufferCacheRuntime::BindTransformFeedbackObject(GPUVAddr tfb_object_addr) { | ||
| 380 | OGLTransformFeedback& tfb_object = tfb_objects[tfb_object_addr]; | ||
| 381 | tfb_object.Create(); | ||
| 382 | glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfb_object.handle); | ||
| 383 | } | ||
| 384 | |||
| 385 | GLuint BufferCacheRuntime::GetTransformFeedbackObject(GPUVAddr tfb_object_addr) { | ||
| 386 | ASSERT(tfb_objects.contains(tfb_object_addr)); | ||
| 387 | return tfb_objects[tfb_object_addr].handle; | ||
| 388 | } | ||
| 389 | |||
| 379 | } // namespace OpenGL | 390 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index 1e8708f59..2c18de166 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <array> | 6 | #include <array> |
| 7 | #include <span> | 7 | #include <span> |
| 8 | #include <unordered_map> | ||
| 8 | 9 | ||
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | #include "video_core/buffer_cache/buffer_cache_base.h" | 11 | #include "video_core/buffer_cache/buffer_cache_base.h" |
| @@ -121,6 +122,9 @@ public: | |||
| 121 | void BindImageBuffer(Buffer& buffer, u32 offset, u32 size, | 122 | void BindImageBuffer(Buffer& buffer, u32 offset, u32 size, |
| 122 | VideoCore::Surface::PixelFormat format); | 123 | VideoCore::Surface::PixelFormat format); |
| 123 | 124 | ||
| 125 | void BindTransformFeedbackObject(GPUVAddr tfb_object_addr); | ||
| 126 | GLuint GetTransformFeedbackObject(GPUVAddr tfb_object_addr); | ||
| 127 | |||
| 124 | u64 GetDeviceMemoryUsage() const; | 128 | u64 GetDeviceMemoryUsage() const; |
| 125 | 129 | ||
| 126 | void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) { | 130 | void BindFastUniformBuffer(size_t stage, u32 binding_index, u32 size) { |
| @@ -233,6 +237,7 @@ private: | |||
| 233 | u32 index_buffer_offset = 0; | 237 | u32 index_buffer_offset = 0; |
| 234 | 238 | ||
| 235 | u64 device_access_memory; | 239 | u64 device_access_memory; |
| 240 | std::unordered_map<GPUVAddr, OGLTransformFeedback> tfb_objects; | ||
| 236 | }; | 241 | }; |
| 237 | 242 | ||
| 238 | struct BufferCacheParams { | 243 | struct BufferCacheParams { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 339950d2e..7a5fad735 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -309,6 +309,13 @@ void RasterizerOpenGL::DrawIndirect() { | |||
| 309 | const auto& params = maxwell3d->draw_manager->GetIndirectParams(); | 309 | const auto& params = maxwell3d->draw_manager->GetIndirectParams(); |
| 310 | buffer_cache.SetDrawIndirect(¶ms); | 310 | buffer_cache.SetDrawIndirect(¶ms); |
| 311 | PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { | 311 | PrepareDraw(params.is_indexed, [this, ¶ms](GLenum primitive_mode) { |
| 312 | if (params.is_byte_count) { | ||
| 313 | const GPUVAddr tfb_object_base_addr = params.indirect_start_address - 4U; | ||
| 314 | const GLuint tfb_object = | ||
| 315 | buffer_cache_runtime.GetTransformFeedbackObject(tfb_object_base_addr); | ||
| 316 | glDrawTransformFeedback(primitive_mode, tfb_object); | ||
| 317 | return; | ||
| 318 | } | ||
| 312 | const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); | 319 | const auto [buffer, offset] = buffer_cache.GetDrawIndirectBuffer(); |
| 313 | const GLvoid* const gl_offset = | 320 | const GLvoid* const gl_offset = |
| 314 | reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset)); | 321 | reinterpret_cast<const GLvoid*>(static_cast<uintptr_t>(offset)); |
| @@ -1371,6 +1378,10 @@ void RasterizerOpenGL::ReleaseChannel(s32 channel_id) { | |||
| 1371 | query_cache.EraseChannel(channel_id); | 1378 | query_cache.EraseChannel(channel_id); |
| 1372 | } | 1379 | } |
| 1373 | 1380 | ||
| 1381 | void RasterizerOpenGL::RegisterTransformFeedback(GPUVAddr tfb_object_addr) { | ||
| 1382 | buffer_cache_runtime.BindTransformFeedbackObject(tfb_object_addr); | ||
| 1383 | } | ||
| 1384 | |||
| 1374 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_) | 1385 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_, TextureCache& texture_cache_) |
| 1375 | : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {} | 1386 | : buffer_cache{buffer_cache_}, texture_cache{texture_cache_} {} |
| 1376 | 1387 | ||
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index b79d7a70c..ce3460938 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -139,6 +139,12 @@ public: | |||
| 139 | 139 | ||
| 140 | void ReleaseChannel(s32 channel_id) override; | 140 | void ReleaseChannel(s32 channel_id) override; |
| 141 | 141 | ||
| 142 | void RegisterTransformFeedback(GPUVAddr tfb_object_addr) override; | ||
| 143 | |||
| 144 | bool HasDrawTransformFeedback() override { | ||
| 145 | return true; | ||
| 146 | } | ||
| 147 | |||
| 142 | private: | 148 | private: |
| 143 | static constexpr size_t MAX_TEXTURES = 192; | 149 | static constexpr size_t MAX_TEXTURES = 192; |
| 144 | static constexpr size_t MAX_IMAGES = 48; | 150 | static constexpr size_t MAX_IMAGES = 48; |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.cpp b/src/video_core/renderer_opengl/gl_resource_manager.cpp index eae8fd110..1d2c9b70a 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.cpp +++ b/src/video_core/renderer_opengl/gl_resource_manager.cpp | |||
| @@ -207,4 +207,21 @@ void OGLQuery::Release() { | |||
| 207 | handle = 0; | 207 | handle = 0; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | void OGLTransformFeedback::Create() { | ||
| 211 | if (handle != 0) | ||
| 212 | return; | ||
| 213 | |||
| 214 | MICROPROFILE_SCOPE(OpenGL_ResourceCreation); | ||
| 215 | glCreateTransformFeedbacks(1, &handle); | ||
| 216 | } | ||
| 217 | |||
| 218 | void OGLTransformFeedback::Release() { | ||
| 219 | if (handle == 0) | ||
| 220 | return; | ||
| 221 | |||
| 222 | MICROPROFILE_SCOPE(OpenGL_ResourceDeletion); | ||
| 223 | glDeleteTransformFeedbacks(1, &handle); | ||
| 224 | handle = 0; | ||
| 225 | } | ||
| 226 | |||
| 210 | } // namespace OpenGL | 227 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_resource_manager.h b/src/video_core/renderer_opengl/gl_resource_manager.h index 77362acd2..6ca8227bd 100644 --- a/src/video_core/renderer_opengl/gl_resource_manager.h +++ b/src/video_core/renderer_opengl/gl_resource_manager.h | |||
| @@ -323,4 +323,31 @@ public: | |||
| 323 | GLuint handle = 0; | 323 | GLuint handle = 0; |
| 324 | }; | 324 | }; |
| 325 | 325 | ||
| 326 | class OGLTransformFeedback final { | ||
| 327 | public: | ||
| 328 | YUZU_NON_COPYABLE(OGLTransformFeedback); | ||
| 329 | |||
| 330 | OGLTransformFeedback() = default; | ||
| 331 | |||
| 332 | OGLTransformFeedback(OGLTransformFeedback&& o) noexcept : handle(std::exchange(o.handle, 0)) {} | ||
| 333 | |||
| 334 | ~OGLTransformFeedback() { | ||
| 335 | Release(); | ||
| 336 | } | ||
| 337 | |||
| 338 | OGLTransformFeedback& operator=(OGLTransformFeedback&& o) noexcept { | ||
| 339 | Release(); | ||
| 340 | handle = std::exchange(o.handle, 0); | ||
| 341 | return *this; | ||
| 342 | } | ||
| 343 | |||
| 344 | /// Creates a new internal OpenGL resource and stores the handle | ||
| 345 | void Create(); | ||
| 346 | |||
| 347 | /// Deletes the internal OpenGL resource | ||
| 348 | void Release(); | ||
| 349 | |||
| 350 | GLuint handle = 0; | ||
| 351 | }; | ||
| 352 | |||
| 326 | } // namespace OpenGL | 353 | } // namespace OpenGL |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index a6fbca69e..727bbd98d 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -755,10 +755,10 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags | |||
| 755 | // The wanted format is not supported by hardware, search for alternatives | 755 | // The wanted format is not supported by hardware, search for alternatives |
| 756 | const VkFormat* alternatives = GetFormatAlternatives(wanted_format); | 756 | const VkFormat* alternatives = GetFormatAlternatives(wanted_format); |
| 757 | if (alternatives == nullptr) { | 757 | if (alternatives == nullptr) { |
| 758 | ASSERT_MSG(false, | 758 | LOG_ERROR(Render_Vulkan, |
| 759 | "Format={} with usage={} and type={} has no defined alternatives and host " | 759 | "Format={} with usage={} and type={} has no defined alternatives and host " |
| 760 | "hardware does not support it", | 760 | "hardware does not support it", |
| 761 | wanted_format, wanted_usage, format_type); | 761 | wanted_format, wanted_usage, format_type); |
| 762 | return wanted_format; | 762 | return wanted_format; |
| 763 | } | 763 | } |
| 764 | 764 | ||
| @@ -774,10 +774,10 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags | |||
| 774 | } | 774 | } |
| 775 | 775 | ||
| 776 | // No alternatives found, panic | 776 | // No alternatives found, panic |
| 777 | ASSERT_MSG(false, | 777 | LOG_ERROR(Render_Vulkan, |
| 778 | "Format={} with usage={} and type={} is not supported by the host hardware and " | 778 | "Format={} with usage={} and type={} is not supported by the host hardware and " |
| 779 | "doesn't support any of the alternatives", | 779 | "doesn't support any of the alternatives", |
| 780 | wanted_format, wanted_usage, format_type); | 780 | wanted_format, wanted_usage, format_type); |
| 781 | return wanted_format; | 781 | return wanted_format; |
| 782 | } | 782 | } |
| 783 | 783 | ||
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index 2f78b8af0..074aed964 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -246,7 +246,9 @@ void SetObjectName(const DeviceDispatch* dld, VkDevice device, T handle, VkObjec | |||
| 246 | .objectHandle = reinterpret_cast<u64>(handle), | 246 | .objectHandle = reinterpret_cast<u64>(handle), |
| 247 | .pObjectName = name, | 247 | .pObjectName = name, |
| 248 | }; | 248 | }; |
| 249 | Check(dld->vkSetDebugUtilsObjectNameEXT(device, &name_info)); | 249 | if (dld->vkSetDebugUtilsObjectNameEXT) { |
| 250 | Check(dld->vkSetDebugUtilsObjectNameEXT(device, &name_info)); | ||
| 251 | } | ||
| 250 | } | 252 | } |
| 251 | 253 | ||
| 252 | } // Anonymous namespace | 254 | } // Anonymous namespace |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 530e445f9..366e806d5 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -168,14 +168,6 @@ class GMainWindow : public QMainWindow { | |||
| 168 | /// Max number of recently loaded items to keep track of | 168 | /// Max number of recently loaded items to keep track of |
| 169 | static const int max_recent_files_item = 10; | 169 | static const int max_recent_files_item = 10; |
| 170 | 170 | ||
| 171 | // TODO: Make use of this! | ||
| 172 | enum { | ||
| 173 | UI_IDLE, | ||
| 174 | UI_EMU_BOOTING, | ||
| 175 | UI_EMU_RUNNING, | ||
| 176 | UI_EMU_STOPPING, | ||
| 177 | }; | ||
| 178 | |||
| 179 | enum { | 171 | enum { |
| 180 | CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, | 172 | CREATE_SHORTCUT_MSGBOX_FULLSCREEN_YES, |
| 181 | CREATE_SHORTCUT_MSGBOX_SUCCESS, | 173 | CREATE_SHORTCUT_MSGBOX_SUCCESS, |