gsp_gpu: Implement TryAcquireRight and stub SetInternalPriorities. (#7285)
* gsp_gpu: Implement TryAcquireRight. * gsp_gpu: Stub SetInternalPriorities. * gsp_gpu: Move serialization logic into implementation. * gsp_gpu: Replace UINT32_MAX with std::numeric_limits<u32>::max().
This commit is contained in:
parent
b6b98af105
commit
bd4ec251cd
2 changed files with 119 additions and 46 deletions
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <boost/serialization/base_object.hpp>
|
||||||
|
#include <boost/serialization/optional.hpp>
|
||||||
|
#include <boost/serialization/shared_ptr.hpp>
|
||||||
#include "common/archives.h"
|
#include "common/archives.h"
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
|
@ -478,7 +481,7 @@ void GSP_GPU::SignalInterrupt(InterruptId interrupt_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For normal interrupts, don't do anything if no process has acquired the GPU right.
|
// For normal interrupts, don't do anything if no process has acquired the GPU right.
|
||||||
if (active_thread_id == UINT32_MAX) {
|
if (active_thread_id == std::numeric_limits<u32>::max()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,7 +667,7 @@ void GSP_GPU::TriggerCmdReqQueue(Kernel::HLERequestContext& ctx) {
|
||||||
void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) {
|
void GSP_GPU::ImportDisplayCaptureInfo(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(ctx);
|
IPC::RequestParser rp(ctx);
|
||||||
|
|
||||||
if (active_thread_id == UINT32_MAX) {
|
if (active_thread_id == std::numeric_limits<u32>::max()) {
|
||||||
LOG_WARNING(Service_GSP, "Called without an active thread.");
|
LOG_WARNING(Service_GSP, "Called without an active thread.");
|
||||||
|
|
||||||
// TODO: Find the right error code.
|
// TODO: Find the right error code.
|
||||||
|
@ -792,37 +795,57 @@ void GSP_GPU::RestoreVramSysArea(Kernel::HLERequestContext& ctx) {
|
||||||
rb.Push(RESULT_SUCCESS);
|
rb.Push(RESULT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSP_GPU::AcquireRight(Kernel::HLERequestContext& ctx) {
|
ResultCode GSP_GPU::AcquireGpuRight(const Kernel::HLERequestContext& ctx,
|
||||||
IPC::RequestParser rp(ctx);
|
const std::shared_ptr<Kernel::Process>& process, u32 flag,
|
||||||
|
bool blocking) {
|
||||||
|
const auto session_data = GetSessionData(ctx.Session());
|
||||||
|
|
||||||
u32 flag = rp.Pop<u32>();
|
LOG_DEBUG(Service_GSP, "called flag={:08X} process={} thread_id={}", flag, process->process_id,
|
||||||
auto process = rp.PopObject<Kernel::Process>();
|
session_data->thread_id);
|
||||||
|
|
||||||
SessionData* session_data = GetSessionData(ctx.Session());
|
|
||||||
|
|
||||||
LOG_WARNING(Service_GSP, "called flag={:08X} process={} thread_id={}", flag,
|
|
||||||
process->process_id, session_data->thread_id);
|
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
|
||||||
|
|
||||||
if (active_thread_id == session_data->thread_id) {
|
if (active_thread_id == session_data->thread_id) {
|
||||||
rb.Push(ResultCode(ErrorDescription::AlreadyDone, ErrorModule::GX, ErrorSummary::Success,
|
return {ErrorDescription::AlreadyDone, ErrorModule::GX, ErrorSummary::Success,
|
||||||
ErrorLevel::Success));
|
ErrorLevel::Success};
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(Subv): This case should put the caller thread to sleep until the right is released.
|
if (blocking) {
|
||||||
ASSERT_MSG(active_thread_id == UINT32_MAX, "GPU right has already been acquired");
|
// TODO: The thread should be put to sleep until acquired.
|
||||||
|
ASSERT_MSG(active_thread_id == std::numeric_limits<u32>::max(),
|
||||||
|
"Sleeping for GPU right is not yet supported.");
|
||||||
|
} else if (active_thread_id != std::numeric_limits<u32>::max()) {
|
||||||
|
return {ErrorDescription::Busy, ErrorModule::GX, ErrorSummary::WouldBlock,
|
||||||
|
ErrorLevel::Status};
|
||||||
|
}
|
||||||
|
|
||||||
active_thread_id = session_data->thread_id;
|
active_thread_id = session_data->thread_id;
|
||||||
|
return RESULT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
rb.Push(RESULT_SUCCESS);
|
void GSP_GPU::TryAcquireRight(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
const auto process = rp.PopObject<Kernel::Process>();
|
||||||
|
|
||||||
|
const auto result = AcquireGpuRight(ctx, process, 0, false);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
rb.Push(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GSP_GPU::AcquireRight(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
const auto flag = rp.Pop<u32>();
|
||||||
|
const auto process = rp.PopObject<Kernel::Process>();
|
||||||
|
|
||||||
|
const auto result = AcquireGpuRight(ctx, process, flag, true);
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
rb.Push(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSP_GPU::ReleaseRight(const SessionData* session_data) {
|
void GSP_GPU::ReleaseRight(const SessionData* session_data) {
|
||||||
ASSERT_MSG(active_thread_id == session_data->thread_id,
|
ASSERT_MSG(active_thread_id == session_data->thread_id,
|
||||||
"Wrong thread tried to release GPU right");
|
"Wrong thread tried to release GPU right");
|
||||||
active_thread_id = UINT32_MAX;
|
active_thread_id = std::numeric_limits<u32>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSP_GPU::ReleaseRight(Kernel::HLERequestContext& ctx) {
|
void GSP_GPU::ReleaseRight(Kernel::HLERequestContext& ctx) {
|
||||||
|
@ -863,6 +886,18 @@ void GSP_GPU::SetLedForceOff(Kernel::HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_GSP, "(STUBBED) called");
|
LOG_DEBUG(Service_GSP, "(STUBBED) called");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GSP_GPU::SetInternalPriorities(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx);
|
||||||
|
const auto priority = rp.Pop<u32>();
|
||||||
|
const auto priority_with_rights = rp.Pop<u32>();
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
|
LOG_DEBUG(Service_GSP, "(STUBBED) called priority={:#02X}, priority_with_rights={:#02X}",
|
||||||
|
priority, priority_with_rights);
|
||||||
|
}
|
||||||
|
|
||||||
SessionData* GSP_GPU::FindRegisteredThreadData(u32 thread_id) {
|
SessionData* GSP_GPU::FindRegisteredThreadData(u32 thread_id) {
|
||||||
for (auto& session_info : connected_sessions) {
|
for (auto& session_info : connected_sessions) {
|
||||||
SessionData* data = static_cast<SessionData*>(session_info.data.get());
|
SessionData* data = static_cast<SessionData*>(session_info.data.get());
|
||||||
|
@ -874,6 +909,17 @@ SessionData* GSP_GPU::FindRegisteredThreadData(u32 thread_id) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void GSP_GPU::serialize(Archive& ar, const unsigned int) {
|
||||||
|
ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this);
|
||||||
|
ar& shared_memory;
|
||||||
|
ar& active_thread_id;
|
||||||
|
ar& first_initialization;
|
||||||
|
ar& used_thread_ids;
|
||||||
|
ar& saved_vram;
|
||||||
|
}
|
||||||
|
SERIALIZE_IMPL(GSP_GPU)
|
||||||
|
|
||||||
GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system(system) {
|
GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system(system) {
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
@ -897,7 +943,7 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system
|
||||||
{0x0012, nullptr, "GetPerfLog"},
|
{0x0012, nullptr, "GetPerfLog"},
|
||||||
{0x0013, &GSP_GPU::RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"},
|
{0x0013, &GSP_GPU::RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"},
|
||||||
{0x0014, &GSP_GPU::UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"},
|
{0x0014, &GSP_GPU::UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"},
|
||||||
{0x0015, nullptr, "TryAcquireRight"},
|
{0x0015, &GSP_GPU::TryAcquireRight, "TryAcquireRight"},
|
||||||
{0x0016, &GSP_GPU::AcquireRight, "AcquireRight"},
|
{0x0016, &GSP_GPU::AcquireRight, "AcquireRight"},
|
||||||
{0x0017, &GSP_GPU::ReleaseRight, "ReleaseRight"},
|
{0x0017, &GSP_GPU::ReleaseRight, "ReleaseRight"},
|
||||||
{0x0018, &GSP_GPU::ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"},
|
{0x0018, &GSP_GPU::ImportDisplayCaptureInfo, "ImportDisplayCaptureInfo"},
|
||||||
|
@ -906,7 +952,7 @@ GSP_GPU::GSP_GPU(Core::System& system) : ServiceFramework("gsp::Gpu", 4), system
|
||||||
{0x001B, nullptr, "ResetGpuCore"},
|
{0x001B, nullptr, "ResetGpuCore"},
|
||||||
{0x001C, &GSP_GPU::SetLedForceOff, "SetLedForceOff"},
|
{0x001C, &GSP_GPU::SetLedForceOff, "SetLedForceOff"},
|
||||||
{0x001D, nullptr, "SetTestCommand"},
|
{0x001D, nullptr, "SetTestCommand"},
|
||||||
{0x001E, nullptr, "SetInternalPriorities"},
|
{0x001E, &GSP_GPU::SetInternalPriorities, "SetInternalPriorities"},
|
||||||
{0x001F, &GSP_GPU::StoreDataCache, "StoreDataCache"},
|
{0x001F, &GSP_GPU::StoreDataCache, "StoreDataCache"},
|
||||||
// clang-format on
|
// clang-format on
|
||||||
};
|
};
|
||||||
|
@ -926,6 +972,16 @@ std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> GSP_GPU::MakeSes
|
||||||
return std::make_unique<SessionData>(this);
|
return std::make_unique<SessionData>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void SessionData::serialize(Archive& ar, const unsigned int) {
|
||||||
|
ar& boost::serialization::base_object<Kernel::SessionRequestHandler::SessionDataBase>(*this);
|
||||||
|
ar& gsp;
|
||||||
|
ar& interrupt_event;
|
||||||
|
ar& thread_id;
|
||||||
|
ar& registered;
|
||||||
|
}
|
||||||
|
SERIALIZE_IMPL(SessionData)
|
||||||
|
|
||||||
SessionData::SessionData(GSP_GPU* gsp) : gsp(gsp) {
|
SessionData::SessionData(GSP_GPU* gsp) : gsp(gsp) {
|
||||||
// Assign a new thread id to this session when it connects. Note: In the real GSP service this
|
// Assign a new thread id to this session when it connects. Note: In the real GSP service this
|
||||||
// is done through a real thread (svcCreateThread) but we have to simulate it since our HLE
|
// is done through a real thread (svcCreateThread) but we have to simulate it since our HLE
|
||||||
|
|
|
@ -7,9 +7,8 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/serialization/base_object.hpp>
|
#include <boost/optional/optional.hpp>
|
||||||
#include <boost/serialization/optional.hpp>
|
#include <boost/serialization/export.hpp>
|
||||||
#include <boost/serialization/shared_ptr.hpp>
|
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/kernel/event.h"
|
#include "core/hle/kernel/event.h"
|
||||||
|
@ -22,6 +21,8 @@ class System;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
class HLERequestContext;
|
||||||
|
class Process;
|
||||||
class SharedMemory;
|
class SharedMemory;
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
||||||
|
@ -214,14 +215,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int);
|
||||||
ar& boost::serialization::base_object<Kernel::SessionRequestHandler::SessionDataBase>(
|
|
||||||
*this);
|
|
||||||
ar& gsp;
|
|
||||||
ar& interrupt_event;
|
|
||||||
ar& thread_id;
|
|
||||||
ar& registered;
|
|
||||||
}
|
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -379,9 +373,25 @@ private:
|
||||||
void UnregisterInterruptRelayQueue(Kernel::HLERequestContext& ctx);
|
void UnregisterInterruptRelayQueue(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GSP_GPU::AcquireRight service function
|
* GSP_GPU::TryAcquireRight service function
|
||||||
|
* Inputs:
|
||||||
|
* 0 : Header code [0x00150002]
|
||||||
|
* 1 : Handle translate header (0x0)
|
||||||
|
* 2 : Process handle
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* 1: Result code
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
void TryAcquireRight(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GSP_GPU::AcquireRight service function
|
||||||
|
* Inputs:
|
||||||
|
* 0 : Header code [0x00160042]
|
||||||
|
* 1 : Flags
|
||||||
|
* 2 : Handle translate header (0x0)
|
||||||
|
* 3 : Process handle
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
*/
|
*/
|
||||||
void AcquireRight(Kernel::HLERequestContext& ctx);
|
void AcquireRight(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
@ -464,6 +474,17 @@ private:
|
||||||
/// Force the 3D LED State (0 = On, Non-Zero = Off)
|
/// Force the 3D LED State (0 = On, Non-Zero = Off)
|
||||||
void SetLedForceOff(Kernel::HLERequestContext& ctx);
|
void SetLedForceOff(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GSP_GPU::SetInternalPriorities service function
|
||||||
|
* Inputs:
|
||||||
|
* 0 : Header code [0x001E0080]
|
||||||
|
* 1 : Session thread priority
|
||||||
|
* 2 : Session thread priority with rights
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
void SetInternalPriorities(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/// Returns the session data for the specified registered thread id, or nullptr if not found.
|
/// Returns the session data for the specified registered thread id, or nullptr if not found.
|
||||||
SessionData* FindRegisteredThreadData(u32 thread_id);
|
SessionData* FindRegisteredThreadData(u32 thread_id);
|
||||||
|
|
||||||
|
@ -471,13 +492,17 @@ private:
|
||||||
|
|
||||||
std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> MakeSessionData() override;
|
std::unique_ptr<Kernel::SessionRequestHandler::SessionDataBase> MakeSessionData() override;
|
||||||
|
|
||||||
|
ResultCode AcquireGpuRight(const Kernel::HLERequestContext& ctx,
|
||||||
|
const std::shared_ptr<Kernel::Process>& process, u32 flag,
|
||||||
|
bool blocking);
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
/// GSP shared memory
|
/// GSP shared memory
|
||||||
std::shared_ptr<Kernel::SharedMemory> shared_memory;
|
std::shared_ptr<Kernel::SharedMemory> shared_memory;
|
||||||
|
|
||||||
/// Thread id that currently has GPU rights or UINT32_MAX if none.
|
/// Thread id that currently has GPU rights or std::numeric_limits<u32>::max() if none.
|
||||||
u32 active_thread_id = UINT32_MAX;
|
u32 active_thread_id = std::numeric_limits<u32>::max();
|
||||||
|
|
||||||
bool first_initialization = true;
|
bool first_initialization = true;
|
||||||
|
|
||||||
|
@ -493,15 +518,7 @@ private:
|
||||||
friend class SessionData;
|
friend class SessionData;
|
||||||
|
|
||||||
template <class Archive>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int) {
|
void serialize(Archive& ar, const unsigned int);
|
||||||
ar& boost::serialization::base_object<Kernel::SessionRequestHandler>(*this);
|
|
||||||
ar& shared_memory;
|
|
||||||
ar& active_thread_id;
|
|
||||||
ar& first_initialization;
|
|
||||||
ar& used_thread_ids;
|
|
||||||
ar& saved_vram;
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue