diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 66 | ||||
-rw-r--r-- | src/core/hle/kernel/address_arbiter.h | 19 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 6 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 15 | ||||
-rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 11 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_3d.h | 13 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_rasterizer.cpp | 4 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.cpp | 5 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_state.h | 1 |
9 files changed, 106 insertions, 34 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 8422d05e0..db189c8e3 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -17,10 +17,10 @@ #include "core/memory.h" namespace Kernel { -namespace { + // Wake up num_to_wake (or all) threads in a vector. -void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s32 num_to_wake) { - auto& system = Core::System::GetInstance(); +void AddressArbiter::WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, + s32 num_to_wake) { // Only process up to 'target' threads, unless 'target' is <= 0, in which case process // them all. std::size_t last = waiting_threads.size(); @@ -32,12 +32,12 @@ void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s3 for (std::size_t i = 0; i < last; i++) { ASSERT(waiting_threads[i]->GetStatus() == ThreadStatus::WaitArb); waiting_threads[i]->SetWaitSynchronizationResult(RESULT_SUCCESS); + RemoveThread(waiting_threads[i]); waiting_threads[i]->SetArbiterWaitAddress(0); waiting_threads[i]->ResumeFromWait(); system.PrepareReschedule(waiting_threads[i]->GetProcessorID()); } } -} // Anonymous namespace AddressArbiter::AddressArbiter(Core::System& system) : system{system} {} AddressArbiter::~AddressArbiter() = default; @@ -184,6 +184,7 @@ ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 t ResultCode AddressArbiter::WaitForAddressImpl(VAddr address, s64 timeout) { Thread* current_thread = system.CurrentScheduler().GetCurrentThread(); current_thread->SetArbiterWaitAddress(address); + InsertThread(SharedFrom(current_thread)); current_thread->SetStatus(ThreadStatus::WaitArb); current_thread->InvalidateWakeupCallback(); current_thread->WakeAfterDelay(timeout); @@ -192,26 +193,51 @@ ResultCode AddressArbiter::WaitForAddressImpl(VAddr address, s64 timeout) { return RESULT_TIMEOUT; } -std::vector<std::shared_ptr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress( - VAddr address) const { - - // Retrieve all threads that are waiting for this address. - std::vector<std::shared_ptr<Thread>> threads; - const auto& scheduler = system.GlobalScheduler(); - const auto& thread_list = scheduler.GetThreadList(); +void AddressArbiter::HandleWakeupThread(std::shared_ptr<Thread> thread) { + ASSERT(thread->GetStatus() == ThreadStatus::WaitArb); + RemoveThread(thread); + thread->SetArbiterWaitAddress(0); +} - for (const auto& thread : thread_list) { - if (thread->GetArbiterWaitAddress() == address) { - threads.push_back(thread); +void AddressArbiter::InsertThread(std::shared_ptr<Thread> thread) { + const VAddr arb_addr = thread->GetArbiterWaitAddress(); + std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr]; + auto it = thread_list.begin(); + while (it != thread_list.end()) { + const std::shared_ptr<Thread>& current_thread = *it; + if (current_thread->GetPriority() >= thread->GetPriority()) { + thread_list.insert(it, thread); + return; } + ++it; } + thread_list.push_back(std::move(thread)); +} - // Sort them by priority, such that the highest priority ones come first. - std::sort(threads.begin(), threads.end(), - [](const std::shared_ptr<Thread>& lhs, const std::shared_ptr<Thread>& rhs) { - return lhs->GetPriority() < rhs->GetPriority(); - }); +void AddressArbiter::RemoveThread(std::shared_ptr<Thread> thread) { + const VAddr arb_addr = thread->GetArbiterWaitAddress(); + std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[arb_addr]; + auto it = thread_list.begin(); + while (it != thread_list.end()) { + const std::shared_ptr<Thread>& current_thread = *it; + if (current_thread.get() == thread.get()) { + thread_list.erase(it); + return; + } + ++it; + } + UNREACHABLE(); +} - return threads; +std::vector<std::shared_ptr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) { + std::vector<std::shared_ptr<Thread>> result; + std::list<std::shared_ptr<Thread>>& thread_list = arb_threads[address]; + auto it = thread_list.begin(); + while (it != thread_list.end()) { + std::shared_ptr<Thread> current_thread = *it; + result.push_back(std::move(current_thread)); + ++it; + } + return result; } } // namespace Kernel diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h index 1e1f00e60..386983e54 100644 --- a/src/core/hle/kernel/address_arbiter.h +++ b/src/core/hle/kernel/address_arbiter.h @@ -4,7 +4,9 @@ #pragma once +#include <list> #include <memory> +#include <unordered_map> #include <vector> #include "common/common_types.h" @@ -48,6 +50,9 @@ public: /// Waits on an address with a particular arbitration type. ResultCode WaitForAddress(VAddr address, ArbitrationType type, s32 value, s64 timeout_ns); + /// Removes a thread from the container and resets its address arbiter adress to 0 + void HandleWakeupThread(std::shared_ptr<Thread> thread); + private: /// Signals an address being waited on. ResultCode SignalToAddressOnly(VAddr address, s32 num_to_wake); @@ -71,8 +76,20 @@ private: // Waits on the given address with a timeout in nanoseconds ResultCode WaitForAddressImpl(VAddr address, s64 timeout); + /// Wake up num_to_wake (or all) threads in a vector. + void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s32 num_to_wake); + + /// Insert a thread into the address arbiter container + void InsertThread(std::shared_ptr<Thread> thread); + + /// Removes a thread from the address arbiter container + void RemoveThread(std::shared_ptr<Thread> thread); + // Gets the threads waiting on an address. - std::vector<std::shared_ptr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const; + std::vector<std::shared_ptr<Thread>> GetThreadsWaitingOnAddress(VAddr address); + + /// List of threads waiting for a address arbiter + std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> arb_threads; Core::System& system; }; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 0b149067a..1d0783bd3 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -78,9 +78,9 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ } } - if (thread->GetArbiterWaitAddress() != 0) { - ASSERT(thread->GetStatus() == ThreadStatus::WaitArb); - thread->SetArbiterWaitAddress(0); + if (thread->GetStatus() == ThreadStatus::WaitArb) { + auto& address_arbiter = thread->GetOwnerProcess()->GetAddressArbiter(); + address_arbiter.HandleWakeupThread(thread); } if (resume) { diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index bd25de478..35ff26c39 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1781,6 +1781,17 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, u32 type, return address_arbiter.SignalToAddress(address, signal_type, value, num_to_wake); } +static void KernelDebug([[maybe_unused]] Core::System& system, + [[maybe_unused]] u32 kernel_debug_type, [[maybe_unused]] u64 param1, + [[maybe_unused]] u64 param2, [[maybe_unused]] u64 param3) { + // Intentionally do nothing, as this does nothing in released kernel binaries. +} + +static void ChangeKernelTraceState([[maybe_unused]] Core::System& system, + [[maybe_unused]] u32 trace_state) { + // Intentionally do nothing, as this does nothing in released kernel binaries. +} + /// This returns the total CPU ticks elapsed since the CPU was powered-on static u64 GetSystemTick(Core::System& system) { LOG_TRACE(Kernel_SVC, "called"); @@ -2418,8 +2429,8 @@ static const FunctionDef SVC_Table[] = { {0x39, nullptr, "Unknown"}, {0x3A, nullptr, "Unknown"}, {0x3B, nullptr, "Unknown"}, - {0x3C, nullptr, "DumpInfo"}, - {0x3D, nullptr, "DumpInfoNew"}, + {0x3C, SvcWrap<KernelDebug>, "KernelDebug"}, + {0x3D, SvcWrap<ChangeKernelTraceState>, "ChangeKernelTraceState"}, {0x3E, nullptr, "Unknown"}, {0x3F, nullptr, "Unknown"}, {0x40, nullptr, "CreateSession"}, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index c2d8d0dc3..9452e3b6f 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -311,6 +311,17 @@ void SvcWrap(Core::System& system) { func(system); } +template <void func(Core::System&, u32)> +void SvcWrap(Core::System& system) { + func(system, static_cast<u32>(Param(system, 0))); +} + +template <void func(Core::System&, u32, u64, u64, u64)> +void SvcWrap(Core::System& system) { + func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2), + Param(system, 3)); +} + template <void func(Core::System&, s64)> void SvcWrap(Core::System& system) { func(system, static_cast<s64>(Param(system, 0))); diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index dcc7cd1fe..dbb4e597f 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -310,6 +310,11 @@ public: } }; + enum class DepthMode : u32 { + MinusOneToOne = 0, + ZeroToOne = 1, + }; + enum class PrimitiveTopology : u32 { Points = 0x0, Lines = 0x1, @@ -491,11 +496,6 @@ public: INSERT_UNION_PADDING_WORDS(1); }; - enum class DepthMode : u32 { - MinusOneToOne = 0, - ZeroToOne = 1, - }; - enum class TessellationPrimitive : u32 { Isolines = 0, Triangles = 1, @@ -676,7 +676,7 @@ public: u32 count; } vertex_buffer; - INSERT_UNION_PADDING_WORDS(1); + DepthMode depth_mode; float clear_color[4]; float clear_depth; @@ -1425,6 +1425,7 @@ ASSERT_REG_POSITION(rt, 0x200); ASSERT_REG_POSITION(viewport_transform, 0x280); ASSERT_REG_POSITION(viewports, 0x300); ASSERT_REG_POSITION(vertex_buffer, 0x35D); +ASSERT_REG_POSITION(depth_mode, 0x35F); ASSERT_REG_POSITION(clear_color[0], 0x360); ASSERT_REG_POSITION(clear_depth, 0x364); ASSERT_REG_POSITION(clear_stencil, 0x368); diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 9eef7fcd2..88d78d2ad 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp @@ -1028,6 +1028,10 @@ void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { flip_y = !flip_y; } state.clip_control.origin = flip_y ? GL_UPPER_LEFT : GL_LOWER_LEFT; + state.clip_control.depth_mode = + regs.depth_mode == Tegra::Engines::Maxwell3D::Regs::DepthMode::ZeroToOne + ? GL_ZERO_TO_ONE + : GL_NEGATIVE_ONE_TO_ONE; } void RasterizerOpenGL::SyncClipEnabled( diff --git a/src/video_core/renderer_opengl/gl_state.cpp b/src/video_core/renderer_opengl/gl_state.cpp index 39b3986d3..ccc1e050a 100644 --- a/src/video_core/renderer_opengl/gl_state.cpp +++ b/src/video_core/renderer_opengl/gl_state.cpp @@ -411,8 +411,9 @@ void OpenGLState::ApplyAlphaTest() { } void OpenGLState::ApplyClipControl() { - if (UpdateValue(cur_state.clip_control.origin, clip_control.origin)) { - glClipControl(clip_control.origin, GL_NEGATIVE_ONE_TO_ONE); + if (UpdateTie(std::tie(cur_state.clip_control.origin, cur_state.clip_control.depth_mode), + std::tie(clip_control.origin, clip_control.depth_mode))) { + glClipControl(clip_control.origin, clip_control.depth_mode); } } diff --git a/src/video_core/renderer_opengl/gl_state.h b/src/video_core/renderer_opengl/gl_state.h index e53c2c5f2..0b5895084 100644 --- a/src/video_core/renderer_opengl/gl_state.h +++ b/src/video_core/renderer_opengl/gl_state.h @@ -150,6 +150,7 @@ public: struct { GLenum origin = GL_LOWER_LEFT; + GLenum depth_mode = GL_NEGATIVE_ONE_TO_ONE; } clip_control; OpenGLState(); |