Compare commits

..

6 Commits

Author SHA1 Message Date
NekokoTime
bbca3bed08 Update result.h
Remove Copyright 2014 Citra Emulator Project add Copyright 2018 Yuzu Emulator Project
2018-05-18 19:08:33 -03:00
greggameplayer
7eecd15c50 Update README.md 2018-05-17 22:18:23 +02:00
greggameplayer
63e9607390 Update README.md 2018-05-17 22:01:16 +02:00
greggameplayer
7ef5169c05 Update fatal.cpp 2018-05-17 21:51:11 +02:00
greggameplayer
2c48048538 update void name of the changed services name 2018-05-17 21:49:22 +02:00
greggameplayer
28d8135769 update services name 2018-05-17 21:47:00 +02:00
53 changed files with 293 additions and 1139 deletions

View File

@@ -1,7 +1,7 @@
yuzu emulator
=============
[![Travis CI Build Status](https://travis-ci.org/yuzu-emu/yuzu.svg?branch=master)](https://travis-ci.org/yuzu-emu/yuzu)
[![AppVeyor CI Build Status](https://ci.appveyor.com/api/projects/status/77k97svb2usreu68?svg=true)](https://ci.appveyor.com/project/bunnei/yuzu)
[![Build Status Travis](https://travis-ci.com/greggameplayer/yuzu.svg?branch=master)](https://travis-ci.com/greggameplayer/yuzu)
[![Build status Appveyor](https://ci.appveyor.com/api/projects/status/pipaumalhd8uo2jm?svg=true)](https://ci.appveyor.com/project/greggameplayer/yuzu)
yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).

View File

@@ -35,7 +35,6 @@ namespace Log {
SUB(Service, AM) \
SUB(Service, AOC) \
SUB(Service, APM) \
SUB(Service, BCAT) \
SUB(Service, Fatal) \
SUB(Service, Friend) \
SUB(Service, FS) \

View File

@@ -55,7 +55,6 @@ enum class Class : ClassType {
Service_AOC, ///< The AOC (AddOn Content) service
Service_APM, ///< The APM (Performance) service
Service_Audio, ///< The Audio (Audio control) service
Service_BCAT, ///< The BCAT service
Service_Fatal, ///< The Fatal service
Service_Friend, ///< The friend service
Service_FS, ///< The FS (Filesystem) service

View File

@@ -124,10 +124,6 @@ add_library(core STATIC
hle/service/audio/audren_u.h
hle/service/audio/codecctl.cpp
hle/service/audio/codecctl.h
hle/service/bcat/module.cpp
hle/service/bcat/module.h
hle/service/bcat/bcat.cpp
hle/service/bcat/bcat.h
hle/service/fatal/fatal.cpp
hle/service/fatal/fatal.h
hle/service/fatal/fatal_p.cpp

View File

@@ -29,14 +29,9 @@ enum class ControlCommand : u32 {
};
enum class CommandType : u32 {
Invalid = 0,
LegacyRequest = 1,
Close = 2,
LegacyControl = 3,
Request = 4,
Control = 5,
RequestWithContext = 6,
ControlWithContext = 7,
Unspecified,
};

View File

@@ -110,9 +110,7 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
// Padding to align to 16 bytes
rp.AlignWithPadding();
if (Session()->IsDomain() && ((command_header->type == IPC::CommandType::Request ||
command_header->type == IPC::CommandType::RequestWithContext) ||
!incoming)) {
if (Session()->IsDomain() && (command_header->type == IPC::CommandType::Request || !incoming)) {
// If this is an incoming message, only CommandType "Request" has a domain header
// All outgoing domain messages have the domain header, if only incoming has it
if (incoming || domain_message_header) {

View File

@@ -104,6 +104,7 @@ ResultCode Mutex::Release(VAddr address) {
// There are no more threads waiting for the mutex, release it completely.
if (thread == nullptr) {
ASSERT(GetCurrentThread()->wait_mutex_threads.empty());
Memory::Write32(address, 0);
return RESULT_SUCCESS;
}

View File

@@ -145,6 +145,36 @@ static bool DefaultThreadWakeupCallback(ThreadWakeupReason reason, SharedPtr<Thr
return true;
};
/// Wait for a kernel object to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization1(
SharedPtr<WaitObject> object, Thread* thread, s64 nano_seconds = -1,
std::function<Thread::WakeupCallback> wakeup_callback = DefaultThreadWakeupCallback) {
if (!object) {
return ERR_INVALID_HANDLE;
}
if (object->ShouldWait(thread)) {
if (nano_seconds == 0) {
return RESULT_TIMEOUT;
}
thread->wait_objects = {object};
object->AddWaitingThread(thread);
thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
// Create an event to wake the thread up after the specified nanosecond delay has passed
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = wakeup_callback;
Core::System::GetInstance().PrepareReschedule();
} else {
object->Acquire(thread);
}
return RESULT_SUCCESS;
}
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 handle_count,
s64 nano_seconds) {
@@ -202,7 +232,7 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
thread->WakeAfterDelay(nano_seconds);
thread->wakeup_callback = DefaultThreadWakeupCallback;
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
Core::System::GetInstance().PrepareReschedule();
return RESULT_TIMEOUT;
}
@@ -365,7 +395,7 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
thread->SetPriority(priority);
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
Core::System::GetInstance().PrepareReschedule();
return RESULT_SUCCESS;
}
@@ -522,7 +552,6 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
*out_handle = thread->guest_handle;
Core::System::GetInstance().PrepareReschedule();
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
NGLOG_TRACE(Kernel_SVC,
"called entrypoint=0x{:08X} ({}), arg=0x{:08X}, stacktop=0x{:08X}, "
@@ -541,10 +570,7 @@ static ResultCode StartThread(Handle thread_handle) {
return ERR_INVALID_HANDLE;
}
ASSERT(thread->status == THREADSTATUS_DORMANT);
thread->ResumeFromWait();
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
return RESULT_SUCCESS;
}
@@ -608,78 +634,61 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
NGLOG_TRACE(Kernel_SVC, "called, condition_variable_addr=0x{:X}, target=0x{:08X}",
condition_variable_addr, target);
auto RetrieveWaitingThreads =
[](size_t core_index, std::vector<SharedPtr<Thread>>& waiting_threads, VAddr condvar_addr) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
auto& thread_list = scheduler->GetThreadList();
u32 processed = 0;
for (auto& thread : thread_list) {
if (thread->condvar_wait_address == condvar_addr)
waiting_threads.push_back(thread);
auto signal_process_wide_key = [&](size_t core_index) {
const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
for (auto& thread : scheduler->GetThreadList()) {
if (thread->condvar_wait_address != condition_variable_addr)
continue;
// Only process up to 'target' threads, unless 'target' is -1, in which case process
// them all.
if (target != -1 && processed >= target)
break;
// If the mutex is not yet acquired, acquire it.
u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
if (mutex_val == 0) {
// We were able to acquire the mutex, resume this thread.
Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
auto lock_owner = thread->lock_owner;
if (lock_owner)
lock_owner->RemoveMutexWaiter(thread);
thread->lock_owner = nullptr;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
} else {
// Couldn't acquire the mutex, block the thread.
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->status != THREADSTATUS_RUNNING);
thread->status = THREADSTATUS_WAIT_MUTEX;
thread->wakeup_callback = nullptr;
// Signal that the mutex now has a waiting thread.
Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
owner->AddMutexWaiter(thread);
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
}
};
// Retrieve a list of all threads that are waiting for this condition variable.
std::vector<SharedPtr<Thread>> waiting_threads;
RetrieveWaitingThreads(0, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(1, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(2, waiting_threads, condition_variable_addr);
RetrieveWaitingThreads(3, waiting_threads, condition_variable_addr);
// Sort them by priority, such that the highest priority ones come first.
std::sort(waiting_threads.begin(), waiting_threads.end(),
[](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
return lhs->current_priority < rhs->current_priority;
});
// Only process up to 'target' threads, unless 'target' is -1, in which case process
// them all.
size_t last = waiting_threads.size();
if (target != -1)
last = target;
// If there are no threads waiting on this condition variable, just exit
if (last > waiting_threads.size())
return RESULT_SUCCESS;
for (size_t index = 0; index < last; ++index) {
auto& thread = waiting_threads[index];
ASSERT(thread->condvar_wait_address == condition_variable_addr);
// If the mutex is not yet acquired, acquire it.
u32 mutex_val = Memory::Read32(thread->mutex_wait_address);
if (mutex_val == 0) {
// We were able to acquire the mutex, resume this thread.
Memory::Write32(thread->mutex_wait_address, thread->wait_handle);
ASSERT(thread->status == THREADSTATUS_WAIT_MUTEX);
thread->ResumeFromWait();
auto lock_owner = thread->lock_owner;
if (lock_owner)
lock_owner->RemoveMutexWaiter(thread);
thread->lock_owner = nullptr;
thread->mutex_wait_address = 0;
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
} else {
// Couldn't acquire the mutex, block the thread.
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
auto owner = g_handle_table.Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->status != THREADSTATUS_RUNNING);
thread->status = THREADSTATUS_WAIT_MUTEX;
thread->wakeup_callback = nullptr;
// Signal that the mutex now has a waiting thread.
Memory::Write32(thread->mutex_wait_address, mutex_val | Mutex::MutexHasWaitersFlag);
owner->AddMutexWaiter(thread);
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
++processed;
}
}
};
signal_process_wide_key(0);
signal_process_wide_key(1);
signal_process_wide_key(2);
signal_process_wide_key(3);
return RESULT_SUCCESS;
}

View File

@@ -47,12 +47,9 @@ enum class GetInfoType : u64 {
NewMapRegionSize = 15,
// 3.0.0+
IsVirtualAddressMemoryEnabled = 16,
PersonalMmHeapUsage = 17,
TitleId = 18,
// 4.0.0+
PrivilegedProcessId = 19,
// 5.0.0+
UserExceptionContextAddr = 20,
};
void CallSVC(u32 immediate);

View File

@@ -1,4 +1,4 @@
// Copyright 2014 Citra Emulator Project
// Copyright 2018 Yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -32,8 +32,7 @@ enum class ErrorModule : u32 {
Common = 0,
Kernel = 1,
FS = 2,
OS = 3, // used for Memory, Thread, Mutex, Nvidia
HTCS = 4,
NvidiaTransferMemory = 3,
NCM = 5,
DD = 6,
LR = 8,
@@ -43,80 +42,41 @@ enum class ErrorModule : u32 {
PM = 15,
NS = 16,
HTC = 18,
NCMContent = 20,
SM = 21,
RO = 22,
SDMMC = 24,
OVLN = 25,
SPL = 26,
ETHC = 100,
I2C = 101,
GPIO = 102,
UART = 103,
Settings = 105,
WLAN = 107,
XCD = 108,
NIFM = 110,
Hwopus = 111,
Bluetooth = 113,
VI = 114,
NFP = 115,
Time = 116,
Display = 114,
NTC = 116,
FGM = 117,
OE = 118,
PCIe = 120,
PCIE = 120,
Friends = 121,
BCAT = 122,
SSL = 123,
Account = 124,
News = 125,
Mii = 126,
NFC = 127,
AM = 128,
PlayReport = 129,
AHID = 130,
Qlaunch = 132,
PCV = 133,
OMM = 134,
BPC = 135,
PSM = 136,
NIM = 137,
PSC = 138,
TC = 139,
USB = 140,
NSD = 141,
PCTL = 142,
BTM = 143,
ETicket = 145,
NGC = 146,
ERPT = 147,
APM = 148,
Profiler = 150,
ErrorUpload = 151,
Audio = 153,
NPNS = 154,
NPNSHTTPSTREAM = 155,
ARP = 157,
SWKBD = 158,
BOOT = 159,
NFCMifare = 161,
BOOT = 158,
NFC = 161,
UserlandAssert = 162,
Fatal = 163,
NIMShop = 164,
SPSM = 165,
BGTC = 167,
UserlandCrash = 168,
SREPO = 180,
Dauth = 181,
HID = 202,
LDN = 203,
Irsensor = 205,
HID = 203,
Capture = 206,
Manu = 208,
ATK = 209,
GRC = 212,
Migration = 216,
MigrationLdcServ = 217,
TC = 651,
GeneralWebApplet = 800,
WifiWebAuthApplet = 809,
WhitelistedApplet = 810,

View File

@@ -74,40 +74,7 @@ void IAudioController::GetLibraryAppletExpectedMasterVolume(Kernel::HLERequestCo
rb.Push(volume);
}
IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {
static const FunctionInfo functions[] = {
{0, nullptr, "GetLastForegroundCaptureImage"},
{1, nullptr, "UpdateLastForegroundCaptureImage"},
{2, nullptr, "GetLastApplicationCaptureImage"},
{3, nullptr, "GetCallerAppletCaptureImage"},
{4, nullptr, "UpdateCallerAppletCaptureImage"},
{5, nullptr, "GetLastForegroundCaptureImageEx"},
{6, nullptr, "GetLastApplicationCaptureImageEx"},
{7, nullptr, "GetCallerAppletCaptureImageEx"},
{8, nullptr, "TakeScreenShotOfOwnLayer"}, // 2.0.0+
{9, nullptr, "CopyBetweenCaptureBuffers"}, // 5.0.0+
{10, nullptr, "AcquireLastApplicationCaptureBuffer"},
{11, nullptr, "ReleaseLastApplicationCaptureBuffer"},
{12, nullptr, "AcquireLastForegroundCaptureBuffer"},
{13, nullptr, "ReleaseLastForegroundCaptureBuffer"},
{14, nullptr, "AcquireCallerAppletCaptureBuffer"},
{15, nullptr, "ReleaseCallerAppletCaptureBuffer"},
{16, nullptr, "AcquireLastApplicationCaptureBufferEx"},
{17, nullptr, "AcquireLastForegroundCaptureBufferEx"},
{18, nullptr, "AcquireCallerAppletCaptureBufferEx"},
// 2.0.0+
{20, nullptr, "ClearCaptureBuffer"},
{21, nullptr, "ClearAppletTransitionBuffer"},
// 4.0.0+
{22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"},
{23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"},
{24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"},
{25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"},
{26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"},
{27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"},
};
RegisterHandlers(functions);
}
IDisplayController::IDisplayController() : ServiceFramework("IDisplayController") {}
IDebugFunctions::IDebugFunctions() : ServiceFramework("IDebugFunctions") {}
@@ -490,7 +457,7 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
{20, &IApplicationFunctions::EnsureSaveData, "EnsureSaveData"},
{21, &IApplicationFunctions::GetDesiredLanguage, "GetDesiredLanguage"},
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
{23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
{23, nullptr, "GetDisplayVersion"},
{24, nullptr, "GetLaunchStorageInfoForDebug"},
{25, nullptr, "ExtendSaveData"},
{26, nullptr, "GetSaveDataSize"},
@@ -585,14 +552,6 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) {
NGLOG_WARNING(Service_AM, "(STUBBED) called, result=0x{:08X}", result);
}
void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(1);
rb.Push<u64>(0);
NGLOG_WARNING(Service_AM, "(STUBBED) called");
}
void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
// TODO(bunnei): This should be configurable
IPC::ResponseBuilder rb{ctx, 4};

View File

@@ -18,25 +18,10 @@ class NVFlinger;
namespace AM {
// TODO: Add more languages
enum SystemLanguage {
Japanese = 0,
English = 1, // en-US
French = 2,
German = 3,
Italian = 4,
Spanish = 5,
Chinese = 6,
Korean = 7,
Dutch = 8,
Portuguese = 9,
Russian = 10,
Taiwanese = 11,
BritishEnglish = 12, // en-GB
CanadianFrench = 13,
LatinAmericanSpanish = 14, // es-419
// 4.0.0+
SimplifiedChinese = 15,
TraditionalChinese = 16,
English = 1,
};
class IWindowController final : public ServiceFramework<IWindowController> {
@@ -132,7 +117,6 @@ private:
void CreateApplicationAndRequestToStartForQuest(Kernel::HLERequestContext& ctx);
void EnsureSaveData(Kernel::HLERequestContext& ctx);
void SetTerminateResult(Kernel::HLERequestContext& ctx);
void GetDisplayVersion(Kernel::HLERequestContext& ctx);
void GetDesiredLanguage(Kernel::HLERequestContext& ctx);
void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx);
void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx);

View File

@@ -98,7 +98,7 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
: ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)) {
static const FunctionInfo functions[] = {
{0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
{0x00000000, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
};
RegisterHandlers(functions);
}

View File

@@ -35,8 +35,10 @@ public:
AudInU::AudInU() : ServiceFramework("audin:u") {
static const FunctionInfo functions[] = {
{0, nullptr, "ListAudioIns"}, {1, nullptr, "OpenAudioIn"}, {2, nullptr, "Unknown"},
{3, nullptr, "OpenAudioInAuto"}, {4, nullptr, "ListAudioInsAuto"},
{0, nullptr, "ListAudioIns"},
{1, nullptr, "OpenAudioIn"},
{3, nullptr, "OpenAudioInAuto"},
{4, nullptr, "ListAudioInsAuto"},
};
RegisterHandlers(functions);
}

View File

@@ -196,10 +196,10 @@ void AudOutU::OpenAudioOut(Kernel::HLERequestContext& ctx) {
}
AudOutU::AudOutU() : ServiceFramework("audout:u") {
static const FunctionInfo functions[] = {{0, &AudOutU::ListAudioOuts, "ListAudioOuts"},
{1, &AudOutU::OpenAudioOut, "OpenAudioOut"},
{2, nullptr, "ListAudioOutsAuto"},
{3, nullptr, "OpenAudioOutAuto"}};
static const FunctionInfo functions[] = {{0x00000000, &AudOutU::ListAudioOuts, "ListAudioOuts"},
{0x00000001, &AudOutU::OpenAudioOut, "OpenAudioOut"},
{0x00000002, nullptr, "ListAudioOutsAuto"},
{0x00000003, nullptr, "OpenAudioOutAuto"}};
RegisterHandlers(functions);
}

View File

@@ -20,7 +20,6 @@ public:
{4, nullptr, "RegisterBufferEvent"},
{5, nullptr, "GetReleasedFinalOutputRecorderBuffer"},
{6, nullptr, "ContainsFinalOutputRecorderBuffer"},
{7, nullptr, "Unknown"},
{8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
{9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
};
@@ -31,7 +30,7 @@ public:
AudRecU::AudRecU() : ServiceFramework("audrec:u") {
static const FunctionInfo functions[] = {
{0, nullptr, "OpenFinalOutputRecorder"},
{0x00000000, nullptr, "OpenFinalOutputRecorder"},
};
RegisterHandlers(functions);
}

View File

@@ -2,7 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/alignment.h"
#include "common/logging/log.h"
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
@@ -157,20 +156,19 @@ class IAudioDevice final : public ServiceFramework<IAudioDevice> {
public:
IAudioDevice() : ServiceFramework("IAudioDevice") {
static const FunctionInfo functions[] = {
{0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
{1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
{2, nullptr, "GetAudioDeviceOutputVolume"},
{3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
{4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
{5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
{6, &IAudioDevice::ListAudioDeviceName,
{0x0, &IAudioDevice::ListAudioDeviceName, "ListAudioDeviceName"},
{0x1, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolume"},
{0x2, nullptr, "GetAudioDeviceOutputVolume"},
{0x3, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceName"},
{0x4, &IAudioDevice::QueryAudioDeviceSystemEvent, "QueryAudioDeviceSystemEvent"},
{0x5, &IAudioDevice::GetActiveChannelCount, "GetActiveChannelCount"},
{0x6, &IAudioDevice::ListAudioDeviceName,
"ListAudioDeviceNameAuto"}, // TODO(ogniK): Confirm if autos are identical to non auto
{7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
{8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
{10, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
{11, nullptr, "QueryAudioDeviceInputEvent"},
{12, nullptr, "QueryAudioDeviceOutputEvent"},
};
{0x7, &IAudioDevice::SetAudioDeviceOutputVolume, "SetAudioDeviceOutputVolumeAuto"},
{0x8, nullptr, "GetAudioDeviceOutputVolumeAuto"},
{0xa, &IAudioDevice::GetActiveAudioDeviceName, "GetActiveAudioDeviceNameAuto"},
{0xb, nullptr, "QueryAudioDeviceInputEvent"},
{0xc, nullptr, "QueryAudioDeviceOutputEvent"}};
RegisterHandlers(functions);
buffer_event =
@@ -257,62 +255,12 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) {
}
void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto params = rp.PopRaw<WorkerBufferParameters>();
u64 buffer_sz = Common::AlignUp(4 * params.unknown8, 0x40);
buffer_sz += params.unknownC * 1024;
buffer_sz += 0x940 * (params.unknownC + 1);
buffer_sz += 0x3F0 * params.voice_count;
buffer_sz += Common::AlignUp(8 * (params.unknownC + 1), 0x10);
buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10);
buffer_sz +=
Common::AlignUp((0x3C0 * (params.sink_count + params.unknownC) + 4 * params.sample_count) *
(params.unknown8 + 6),
0x40);
if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) {
u32 count = params.unknownC + 1;
u64 node_count = Common::AlignUp(count, 0x40);
u64 node_state_buffer_sz =
4 * (node_count * node_count) + 0xC * node_count + 2 * (node_count / 8);
u64 edge_matrix_buffer_sz = 0;
node_count = Common::AlignUp(count * count, 0x40);
if (node_count >> 31 != 0) {
edge_matrix_buffer_sz = (node_count | 7) / 8;
} else {
edge_matrix_buffer_sz = node_count / 8;
}
buffer_sz += Common::AlignUp(node_state_buffer_sz + edge_matrix_buffer_sz, 0x10);
}
buffer_sz += 0x20 * (params.effect_count + 4 * params.voice_count) + 0x50;
if (IsFeatureSupported(AudioFeatures::Splitter, params.magic)) {
buffer_sz += 0xE0 * params.unknown2c;
buffer_sz += 0x20 * params.splitter_count;
buffer_sz += Common::AlignUp(4 * params.unknown2c, 0x10);
}
buffer_sz = Common::AlignUp(buffer_sz, 0x40) + 0x170 * params.sink_count;
u64 output_sz = buffer_sz + 0x280 * params.sink_count + 0x4B0 * params.effect_count +
((params.voice_count * 256) | 0x40);
if (params.unknown1c >= 1) {
output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count +
16 * params.voice_count + 16) +
0x658) *
(params.unknown1c + 1) +
0xc0,
0x40) +
output_sz;
}
output_sz = Common::AlignUp(output_sz + 0x1807e, 0x1000);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u64>(output_sz);
rb.Push<u64>(0x4000);
NGLOG_DEBUG(Service_Audio, "called, buffer_size=0x{:X}", output_sz);
NGLOG_WARNING(Service_Audio, "(STUBBED) called");
}
void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
@@ -324,14 +272,4 @@ void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) {
NGLOG_DEBUG(Service_Audio, "called");
}
bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const {
u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap
switch (feature) {
case AudioFeatures::Splitter:
return version_num >= 2;
default:
return false;
}
}
} // namespace Service::Audio

View File

@@ -21,31 +21,6 @@ private:
void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
void GetAudioDevice(Kernel::HLERequestContext& ctx);
struct WorkerBufferParameters {
u32_le sample_rate;
u32_le sample_count;
u32_le unknown8;
u32_le unknownC;
u32_le voice_count;
u32_le sink_count;
u32_le effect_count;
u32_le unknown1c;
u8 unknown20;
u8 padding1[3];
u32_le splitter_count;
u32_le unknown2c;
u8 padding2[4];
u32_le magic;
};
static_assert(sizeof(WorkerBufferParameters) == 52,
"WorkerBufferParameters is an invalid size");
enum class AudioFeatures : u32 {
Splitter,
};
bool IsFeatureSupported(AudioFeatures feature, u32_le revision) const;
};
} // namespace Service::Audio

View File

@@ -11,19 +11,19 @@ namespace Service::Audio {
CodecCtl::CodecCtl() : ServiceFramework("codecctl") {
static const FunctionInfo functions[] = {
{0, nullptr, "InitializeCodecController"},
{1, nullptr, "FinalizeCodecController"},
{2, nullptr, "SleepCodecController"},
{3, nullptr, "WakeCodecController"},
{4, nullptr, "SetCodecVolume"},
{5, nullptr, "GetCodecVolumeMax"},
{6, nullptr, "GetCodecVolumeMin"},
{7, nullptr, "SetCodecActiveTarget"},
{8, nullptr, "GetCodecActiveTarget"},
{9, nullptr, "BindCodecHeadphoneMicJackInterrupt"},
{10, nullptr, "IsCodecHeadphoneMicJackInserted"},
{11, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
{12, nullptr, "IsCodecDeviceRequested"},
{0x00000000, nullptr, "InitializeCodecController"},
{0x00000001, nullptr, "FinalizeCodecController"},
{0x00000002, nullptr, "SleepCodecController"},
{0x00000003, nullptr, "WakeCodecController"},
{0x00000004, nullptr, "SetCodecVolume"},
{0x00000005, nullptr, "GetCodecVolumeMax"},
{0x00000006, nullptr, "GetCodecVolumeMin"},
{0x00000007, nullptr, "SetCodecActiveTarget"},
{0x00000008, nullptr, "Unknown"},
{0x00000009, nullptr, "BindCodecHeadphoneMicJackInterrupt"},
{0x00000010, nullptr, "IsCodecHeadphoneMicJackInserted"},
{0x00000011, nullptr, "ClearCodecHeadphoneMicJackInterrupt"},
{0x00000012, nullptr, "IsCodecDeviceRequested"},
};
RegisterHandlers(functions);
}

View File

@@ -1,16 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/service/bcat/bcat.h"
namespace Service::BCAT {
BCAT::BCAT(std::shared_ptr<Module> module, const char* name)
: Module::Interface(std::move(module), name) {
static const FunctionInfo functions[] = {
{0, &BCAT::CreateBcatService, "CreateBcatService"},
};
RegisterHandlers(functions);
}
} // namespace Service::BCAT

View File

@@ -1,16 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/service/bcat/module.h"
namespace Service::BCAT {
class BCAT final : public Module::Interface {
public:
explicit BCAT(std::shared_ptr<Module> module, const char* name);
};
} // namespace Service::BCAT

View File

@@ -1,53 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/bcat/bcat.h"
#include "core/hle/service/bcat/module.h"
namespace Service::BCAT {
class IBcatService final : public ServiceFramework<IBcatService> {
public:
IBcatService() : ServiceFramework("IBcatService") {
static const FunctionInfo functions[] = {
{10100, nullptr, "RequestSyncDeliveryCache"},
{10101, nullptr, "RequestSyncDeliveryCacheWithDirectoryName"},
{10200, nullptr, "CancelSyncDeliveryCacheRequest"},
{20100, nullptr, "RequestSyncDeliveryCacheWithApplicationId"},
{20101, nullptr, "RequestSyncDeliveryCacheWithApplicationIdAndDirectoryName"},
{30100, nullptr, "SetPassphrase"},
{30200, nullptr, "RegisterBackgroundDeliveryTask"},
{30201, nullptr, "UnregisterBackgroundDeliveryTask"},
{30202, nullptr, "BlockDeliveryTask"},
{30203, nullptr, "UnblockDeliveryTask"},
{90100, nullptr, "EnumerateBackgroundDeliveryTask"},
{90200, nullptr, "GetDeliveryList"},
{90201, nullptr, "ClearDeliveryCacheStorage"},
{90300, nullptr, "GetPushNotificationLog"},
};
RegisterHandlers(functions);
}
};
void Module::Interface::CreateBcatService(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IBcatService>();
NGLOG_DEBUG(Service_BCAT, "called");
}
Module::Interface::Interface(std::shared_ptr<Module> module, const char* name)
: ServiceFramework(name), module(std::move(module)) {}
void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module = std::make_shared<Module>();
std::make_shared<BCAT>(module, "bcat:a")->InstallAsService(service_manager);
std::make_shared<BCAT>(module, "bcat:m")->InstallAsService(service_manager);
std::make_shared<BCAT>(module, "bcat:u")->InstallAsService(service_manager);
std::make_shared<BCAT>(module, "bcat:s")->InstallAsService(service_manager);
}
} // namespace Service::BCAT

View File

@@ -1,27 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/service/service.h"
namespace Service::BCAT {
class Module final {
public:
class Interface : public ServiceFramework<Interface> {
public:
Interface(std::shared_ptr<Module> module, const char* name);
void CreateBcatService(Kernel::HLERequestContext& ctx);
protected:
std::shared_ptr<Module> module;
};
};
/// Registers all BCAT services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Service::BCAT

View File

@@ -329,7 +329,6 @@ public:
{130, nullptr, "SwapNpadAssignment"},
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
{133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
{200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
{201, &Hid::SendVibrationValue, "SendVibrationValue"},
{202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
@@ -337,41 +336,12 @@ public:
{204, nullptr, "PermitVibration"},
{205, nullptr, "IsVibrationPermitted"},
{206, &Hid::SendVibrationValues, "SendVibrationValues"},
{207, nullptr, "SendVibrationGcErmCommand"},
{208, nullptr, "GetActualVibrationGcErmCommand"},
{209, nullptr, "BeginPermitVibrationSession"},
{210, nullptr, "EndPermitVibrationSession"},
{300, nullptr, "ActivateConsoleSixAxisSensor"},
{301, nullptr, "StartConsoleSixAxisSensor"},
{302, nullptr, "StopConsoleSixAxisSensor"},
{303, nullptr, "ActivateSevenSixAxisSensor"},
{304, nullptr, "StartSevenSixAxisSensor"},
{305, nullptr, "StopSevenSixAxisSensor"},
{306, nullptr, "InitializeSevenSixAxisSensor"},
{307, nullptr, "FinalizeSevenSixAxisSensor"},
{308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
{309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
{400, nullptr, "IsUsbFullKeyControllerEnabled"},
{401, nullptr, "EnableUsbFullKeyController"},
{402, nullptr, "IsUsbFullKeyControllerConnected"},
{403, nullptr, "HasBattery"},
{404, nullptr, "HasLeftRightBattery"},
{405, nullptr, "GetNpadInterfaceType"},
{406, nullptr, "GetNpadLeftRightInterfaceType"},
{500, nullptr, "GetPalmaConnectionHandle"},
{501, nullptr, "InitializePalma"},
{502, nullptr, "AcquirePalmaOperationCompleteEvent"},
{503, nullptr, "GetPalmaOperationInfo"},
{504, nullptr, "PlayPalmaActivity"},
{505, nullptr, "SetPalmaFrModeType"},
{506, nullptr, "ReadPalmaStep"},
{507, nullptr, "EnablePalmaStep"},
{508, nullptr, "SuspendPalmaStep"},
{509, nullptr, "ResetPalmaStep"},
{510, nullptr, "ReadPalmaApplicationSection"},
{511, nullptr, "WritePalmaApplicationSection"},
{512, nullptr, "ReadPalmaUniqueCode"},
{513, nullptr, "SetPalmaUniqueCodeInvalid"},
{1000, nullptr, "SetNpadCommunicationMode"},
{1001, nullptr, "GetNpadCommunicationMode"},
};

View File

@@ -12,7 +12,7 @@ namespace Service::HID {
// Begin enums and output structs
constexpr u32 HID_NUM_ENTRIES = 17;
constexpr u32 HID_NUM_LAYOUTS = 2;
constexpr u32 HID_NUM_LAYOUTS = 7;
constexpr s32 HID_JOYSTICK_MAX = 0x8000;
constexpr s32 HID_JOYSTICK_MIN = -0x8000;

View File

@@ -17,30 +17,30 @@ public:
IUser() : ServiceFramework("IUser") {
static const FunctionInfo functions[] = {
{0, &IUser::Initialize, "Initialize"},
{1, nullptr, "Finalize"},
{2, nullptr, "ListDevices"},
{3, nullptr, "StartDetection"},
{4, nullptr, "StopDetection"},
{5, nullptr, "Mount"},
{6, nullptr, "Unmount"},
{7, nullptr, "OpenApplicationArea"},
{8, nullptr, "GetApplicationArea"},
{9, nullptr, "SetApplicationArea"},
{10, nullptr, "Flush"},
{11, nullptr, "Restore"},
{12, nullptr, "CreateApplicationArea"},
{13, nullptr, "GetTagInfo"},
{14, nullptr, "GetRegisterInfo"},
{15, nullptr, "GetCommonInfo"},
{16, nullptr, "GetModelInfo"},
{17, nullptr, "AttachActivateEvent"},
{18, nullptr, "AttachDeactivateEvent"},
{19, nullptr, "GetState"},
{20, nullptr, "GetDeviceState"},
{21, nullptr, "GetNpadId"},
{22, nullptr, "GetApplicationArea2"},
{23, nullptr, "AttachAvailabilityChangeEvent"},
{24, nullptr, "RecreateApplicationArea"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, nullptr, "Unknown5"},
{6, nullptr, "Unknown6"},
{7, nullptr, "Unknown7"},
{8, nullptr, "Unknown8"},
{9, nullptr, "Unknown9"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{14, nullptr, "Unknown14"},
{15, nullptr, "Unknown15"},
{16, nullptr, "Unknown16"},
{17, nullptr, "Unknown17"},
{18, nullptr, "Unknown18"},
{19, nullptr, "Unknown19"},
{20, nullptr, "Unknown20"},
{21, nullptr, "Unknown21"},
{22, nullptr, "Unknown22"},
{23, nullptr, "Unknown23"},
{24, nullptr, "Unknown24"},
};
RegisterHandlers(functions);
}

View File

@@ -26,8 +26,6 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vecto
return BindChannel(input, output);
case IoctlCommand::IocGetVaRegionsCommand:
return GetVARegions(input, output);
case IoctlCommand::IocUnmapBufferCommand:
return UnmapBuffer(input, output);
}
if (static_cast<IoctlCommand>(command.cmd.Value()) == IoctlCommand::IocRemapCommand)
@@ -127,37 +125,6 @@ u32 nvhost_as_gpu::MapBufferEx(const std::vector<u8>& input, std::vector<u8>& ou
params.offset = gpu.memory_manager->MapBufferEx(object->addr, object->size);
}
// Create a new mapping entry for this operation.
ASSERT_MSG(buffer_mappings.find(params.offset) == buffer_mappings.end(),
"Offset is already mapped");
BufferMapping mapping{};
mapping.nvmap_handle = params.nvmap_handle;
mapping.offset = params.offset;
mapping.size = object->size;
buffer_mappings[params.offset] = mapping;
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlUnmapBuffer params{};
std::memcpy(&params, input.data(), input.size());
NGLOG_DEBUG(Service_NVDRV, "called, offset=0x{:X}", params.offset);
auto& gpu = Core::System::GetInstance().GPU();
auto itr = buffer_mappings.find(params.offset);
ASSERT_MSG(itr != buffer_mappings.end(), "Tried to unmap invalid mapping");
params.offset = gpu.memory_manager->UnmapBuffer(params.offset, itr->second.size);
buffer_mappings.erase(itr->second.offset);
std::memcpy(output.data(), &params, output.size());
return 0;
}

View File

@@ -5,7 +5,6 @@
#pragma once
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>
#include "common/common_types.h"
@@ -31,7 +30,6 @@ private:
IocMapBufferExCommand = 0xC0284106,
IocBindChannelCommand = 0x40044101,
IocGetVaRegionsCommand = 0xC0404108,
IocUnmapBufferCommand = 0xC0084105,
};
struct IoctlInitalizeEx {
@@ -78,11 +76,6 @@ private:
};
static_assert(sizeof(IoctlMapBufferEx) == 40, "IoctlMapBufferEx is incorrect size");
struct IoctlUnmapBuffer {
u64_le offset;
};
static_assert(sizeof(IoctlUnmapBuffer) == 8, "IoctlUnmapBuffer is incorrect size");
struct IoctlBindChannel {
u32_le fd;
};
@@ -105,22 +98,12 @@ private:
static_assert(sizeof(IoctlGetVaRegions) == 16 + sizeof(IoctlVaRegion) * 2,
"IoctlGetVaRegions is incorrect size");
struct BufferMapping {
u64 offset;
u64 size;
u32 nvmap_handle;
};
/// Map containing the nvmap object mappings in GPU memory.
std::unordered_map<u64, BufferMapping> buffer_mappings;
u32 channel{};
u32 InitalizeEx(const std::vector<u8>& input, std::vector<u8>& output);
u32 AllocateSpace(const std::vector<u8>& input, std::vector<u8>& output);
u32 Remap(const std::vector<u8>& input, std::vector<u8>& output);
u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output);
u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output);
u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output);

View File

@@ -16,11 +16,7 @@ u32 nvhost_ctrl::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<
case IoctlCommand::IocGetConfigCommand:
return NvOsGetConfigU32(input, output);
case IoctlCommand::IocCtrlEventWaitCommand:
return IocCtrlEventWait(input, output, false);
case IoctlCommand::IocCtrlEventWaitAsyncCommand:
return IocCtrlEventWait(input, output, true);
case IoctlCommand::IocCtrlEventRegisterCommand:
return IocCtrlEventRegister(input, output);
return IocCtrlEventWait(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0;
@@ -40,7 +36,7 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
} else if (!strcmp(params.param_str.data(), "NVRM_GPU_PREVENT_USE")) {
params.config_str[0] = '0';
} else {
params.config_str[0] = '\0';
params.config_str[0] = '0';
}
} else {
UNIMPLEMENTED(); // unknown domain? Only nv has been seen so far on hardware
@@ -49,13 +45,11 @@ u32 nvhost_ctrl::NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output,
bool is_async) {
u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output) {
IocCtrlEventWaitParams params{};
std::memcpy(&params, input.data(), sizeof(params));
NGLOG_WARNING(Service_NVDRV,
"(STUBBED) called, syncpt_id={}, threshold={}, timeout={}, is_async={}",
params.syncpt_id, params.threshold, params.timeout, is_async);
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called, syncpt_id={} threshold={} timeout={}",
params.syncpt_id, params.threshold, params.timeout);
// TODO(Subv): Implement actual syncpt waiting.
params.value = 0;
@@ -63,10 +57,4 @@ u32 nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
u32 nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
// TODO(bunnei): Implement this.
return 0;
}
} // namespace Service::Nvidia::Devices

View File

@@ -26,64 +26,12 @@ private:
IocSyncptIncrCommand = 0x40040015,
IocSyncptWaitCommand = 0xC00C0016,
IocModuleMutexCommand = 0x40080017,
IocModuleRegRDWRCommand = 0xC0180018,
IocModuleRegRDWRCommand = 0xC008010E,
IocSyncptWaitexCommand = 0xC0100019,
IocSyncptReadMaxCommand = 0xC008001A,
IocGetConfigCommand = 0xC183001B,
IocCtrlEventSignalCommand = 0xC004001C,
IocCtrlEventWaitCommand = 0xC010001D,
IocCtrlEventWaitAsyncCommand = 0xC010001E,
IocCtrlEventRegisterCommand = 0xC004001F,
IocCtrlEventUnregisterCommand = 0xC0040020,
IocCtrlEventKillCommand = 0x40080021,
IocGetConfigCommand = 0xC183001B,
};
struct IocSyncptReadParams {
u32_le id;
u32_le value;
};
static_assert(sizeof(IocSyncptReadParams) == 8, "IocSyncptReadParams is incorrect size");
struct IocSyncptIncrParams {
u32_le id;
};
static_assert(sizeof(IocSyncptIncrParams) == 4, "IocSyncptIncrParams is incorrect size");
struct IocSyncptWaitParams {
u32_le id;
u32_le thresh;
s32_le timeout;
};
static_assert(sizeof(IocSyncptWaitParams) == 12, "IocSyncptWaitParams is incorrect size");
struct IocModuleMutexParams {
u32_le id;
u32_le lock; // (0 = unlock and 1 = lock)
};
static_assert(sizeof(IocModuleMutexParams) == 8, "IocModuleMutexParams is incorrect size");
struct IocModuleRegRDWRParams {
u32_le id;
u32_le num_offsets;
u32_le block_size;
u32_le offsets;
u32_le values;
u32_le write;
};
static_assert(sizeof(IocModuleRegRDWRParams) == 24, "IocModuleRegRDWRParams is incorrect size");
struct IocSyncptWaitexParams {
u32_le id;
u32_le thresh;
s32_le timeout;
u32_le value;
};
static_assert(sizeof(IocSyncptWaitexParams) == 16, "IocSyncptWaitexParams is incorrect size");
struct IocSyncptReadMaxParams {
u32_le id;
u32_le value;
};
static_assert(sizeof(IocSyncptReadMaxParams) == 8, "IocSyncptReadMaxParams is incorrect size");
struct IocGetConfigParams {
std::array<char, 0x41> domain_str;
@@ -92,12 +40,6 @@ private:
};
static_assert(sizeof(IocGetConfigParams) == 387, "IocGetConfigParams is incorrect size");
struct IocCtrlEventSignalParams {
u32_le user_event_id;
};
static_assert(sizeof(IocCtrlEventSignalParams) == 4,
"IocCtrlEventSignalParams is incorrect size");
struct IocCtrlEventWaitParams {
u32_le syncpt_id;
u32_le threshold;
@@ -106,37 +48,9 @@ private:
};
static_assert(sizeof(IocCtrlEventWaitParams) == 16, "IocCtrlEventWaitParams is incorrect size");
struct IocCtrlEventWaitAsyncParams {
u32_le syncpt_id;
u32_le threshold;
u32_le timeout;
u32_le value;
};
static_assert(sizeof(IocCtrlEventWaitAsyncParams) == 16,
"IocCtrlEventWaitAsyncParams is incorrect size");
struct IocCtrlEventRegisterParams {
u32_le user_event_id;
};
static_assert(sizeof(IocCtrlEventRegisterParams) == 4,
"IocCtrlEventRegisterParams is incorrect size");
struct IocCtrlEventUnregisterParams {
u32_le user_event_id;
};
static_assert(sizeof(IocCtrlEventUnregisterParams) == 4,
"IocCtrlEventUnregisterParams is incorrect size");
struct IocCtrlEventKill {
u64_le user_events;
};
static_assert(sizeof(IocCtrlEventKill) == 8, "IocCtrlEventKill is incorrect size");
u32 NvOsGetConfigU32(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output, bool is_async);
u32 IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocCtrlEventWait(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices

View File

@@ -24,8 +24,6 @@ u32 nvhost_ctrl_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vec
return ZCullGetCtxSize(input, output);
case IoctlCommand::IocZcullGetInfo:
return ZCullGetInfo(input, output);
case IoctlCommand::IocZbcSetTable:
return ZBCSetTable(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
return 0;
@@ -127,13 +125,4 @@ u32 nvhost_ctrl_gpu::ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>&
return 0;
}
u32 nvhost_ctrl_gpu::ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output) {
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
IoctlZbcSetTable params{};
std::memcpy(&params, input.data(), input.size());
// TODO(ogniK): What does this even actually do?
std::memcpy(output.data(), &params, output.size());
return 0;
}
} // namespace Service::Nvidia::Devices

View File

@@ -25,7 +25,6 @@ private:
IocGetActiveSlotMaskCommand = 0x80084714,
IocZcullGetCtxSizeCommand = 0x80044701,
IocZcullGetInfo = 0x80284702,
IocZbcSetTable = 0x402C4703,
};
struct IoctlGpuCharacteristics {
@@ -118,21 +117,11 @@ private:
static_assert(sizeof(IoctlNvgpuGpuZcullGetInfoArgs) == 40,
"IoctlNvgpuGpuZcullGetInfoArgs is incorrect size");
struct IoctlZbcSetTable {
u32_le color_ds[4];
u32_le color_l2[4];
u32_le depth;
u32_le format;
u32_le type;
};
static_assert(sizeof(IoctlZbcSetTable) == 44, "IoctlZbcSetTable is incorrect size");
u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetTPCMasks(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetActiveSlotMask(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZCullGetCtxSize(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZCullGetInfo(const std::vector<u8>& input, std::vector<u8>& output);
u32 ZBCSetTable(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices

View File

@@ -32,10 +32,6 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
return AllocGPFIFOEx2(input, output);
case IoctlCommand::IocAllocObjCtxCommand:
return AllocateObjectContext(input, output);
case IoctlCommand::IocChannelGetWaitbaseCommand:
return GetWaitbase(input, output);
case IoctlCommand::IocChannelSetTimeoutCommand:
return ChannelSetTimeout(input, output);
}
if (command.group == NVGPU_IOCTL_MAGIC) {
@@ -142,20 +138,4 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
return 0;
}
u32 nvhost_gpu::GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlGetWaitbase params{};
std::memcpy(&params, input.data(), sizeof(IoctlGetWaitbase));
NGLOG_INFO(Service_NVDRV, "called, unknown=0x{:X}", params.unknown);
params.value = 0; // Seems to be hard coded at 0
std::memcpy(output.data(), &params, output.size());
return 0;
}
u32 nvhost_gpu::ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output) {
IoctlChannelSetTimeout params{};
std::memcpy(&params, input.data(), sizeof(IoctlChannelSetTimeout));
NGLOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout);
return 0;
}
} // namespace Service::Nvidia::Devices

View File

@@ -33,8 +33,6 @@ private:
IocChannelSetPriorityCommand = 0x4004480D,
IocAllocGPFIFOEx2Command = 0xC020481A,
IocAllocObjCtxCommand = 0xC0104809,
IocChannelGetWaitbaseCommand = 0xC0080003,
IocChannelSetTimeoutCommand = 0x40044803,
};
enum class CtxObjects : u32_le {
@@ -51,11 +49,6 @@ private:
};
static_assert(sizeof(IoctlSetNvmapFD) == 4, "IoctlSetNvmapFD is incorrect size");
struct IoctlChannelSetTimeout {
u32_le timeout;
};
static_assert(sizeof(IoctlChannelSetTimeout) == 4, "IoctlChannelSetTimeout is incorrect size");
struct IoctlClientData {
u64_le data;
};
@@ -124,13 +117,7 @@ private:
IoctlFence fence_out; // returned new fence object for others to wait on
};
static_assert(sizeof(IoctlSubmitGpfifo) == 16 + sizeof(IoctlFence),
"IoctlSubmitGpfifo is incorrect size");
struct IoctlGetWaitbase {
u32 unknown; // seems to be ignored? Nintendo added this
u32 value;
};
static_assert(sizeof(IoctlGetWaitbase) == 8, "IoctlGetWaitbase is incorrect size");
"submit_gpfifo is incorrect size");
u32_le nvmap_fd{};
u64_le user_data{};
@@ -146,8 +133,6 @@ private:
u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
std::shared_ptr<nvmap> nvmap_dev;
};

View File

@@ -30,8 +30,6 @@ u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& o
return IocFromId(input, output);
case IoctlCommand::Param:
return IocParam(input, output);
case IoctlCommand::Free:
return IocFree(input, output);
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
@@ -47,7 +45,6 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
object->id = next_id++;
object->size = params.size;
object->status = Object::Status::Created;
object->refcount = 1;
u32 handle = next_handle++;
handles[handle] = std::move(object);
@@ -104,8 +101,6 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
[&](const auto& entry) { return entry.second->id == params.id; });
ASSERT(itr != handles.end());
itr->second->refcount++;
// Return the existing handle instead of creating a new one.
params.handle = itr->first;
@@ -119,25 +114,25 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
IocParamParams params;
std::memcpy(&params, input.data(), sizeof(params));
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.param);
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.type);
auto object = GetObject(params.handle);
ASSERT(object);
ASSERT(object->status == Object::Status::Allocated);
switch (static_cast<ParamTypes>(params.param)) {
switch (static_cast<ParamTypes>(params.type)) {
case ParamTypes::Size:
params.result = object->size;
params.value = object->size;
break;
case ParamTypes::Alignment:
params.result = object->align;
params.value = object->align;
break;
case ParamTypes::Heap:
// TODO(Subv): Seems to be a hardcoded value?
params.result = 0x40000000;
params.value = 0x40000000;
break;
case ParamTypes::Kind:
params.result = object->kind;
params.value = object->kind;
break;
default:
UNIMPLEMENTED();
@@ -147,34 +142,4 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
return 0;
}
u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
enum FreeFlags {
Freed = 0,
NotFreedYet = 1,
};
IocFreeParams params;
std::memcpy(&params, input.data(), sizeof(params));
NGLOG_WARNING(Service_NVDRV, "(STUBBED) called");
auto itr = handles.find(params.handle);
ASSERT(itr != handles.end());
itr->second->refcount--;
params.refcount = itr->second->refcount;
params.size = itr->second->size;
if (itr->second->refcount == 0)
params.flags = Freed;
else
params.flags = NotFreedYet;
handles.erase(params.handle);
std::memcpy(output.data(), &params, sizeof(params));
return 0;
}
} // namespace Service::Nvidia::Devices

View File

@@ -34,7 +34,6 @@ public:
u8 kind;
VAddr addr;
Status status;
u32 refcount;
};
std::shared_ptr<Object> GetObject(u32 handle) const {
@@ -59,25 +58,16 @@ private:
Create = 0xC0080101,
FromId = 0xC0080103,
Alloc = 0xC0200104,
Free = 0xC0180105,
Param = 0xC00C0109,
GetId = 0xC008010E,
GetId = 0xC008010E
};
struct IocCreateParams {
// Input
u32_le size;
// Output
u32_le handle;
};
static_assert(sizeof(IocCreateParams) == 8, "IocCreateParams has wrong size");
struct IocFromIdParams {
// Input
u32_le id;
// Output
u32_le handle;
};
static_assert(sizeof(IocFromIdParams) == 8, "IocFromIdParams has wrong size");
struct IocAllocParams {
// Input
@@ -89,25 +79,6 @@ private:
INSERT_PADDING_BYTES(7);
u64_le addr;
};
static_assert(sizeof(IocAllocParams) == 32, "IocAllocParams has wrong size");
struct IocFreeParams {
u32_le handle;
INSERT_PADDING_BYTES(4);
u64_le refcount;
u32_le size;
u32_le flags;
};
static_assert(sizeof(IocFreeParams) == 24, "IocFreeParams has wrong size");
struct IocParamParams {
// Input
u32_le handle;
u32_le param;
// Output
u32_le result;
};
static_assert(sizeof(IocParamParams) == 12, "IocParamParams has wrong size");
struct IocGetIdParams {
// Output
@@ -115,14 +86,27 @@ private:
// Input
u32_le handle;
};
static_assert(sizeof(IocGetIdParams) == 8, "IocGetIdParams has wrong size");
struct IocFromIdParams {
// Input
u32_le id;
// Output
u32_le handle;
};
struct IocParamParams {
// Input
u32_le handle;
u32_le type;
// Output
u32_le value;
};
u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocFree(const std::vector<u8>& input, std::vector<u8>& output);
};
} // namespace Service::Nvidia::Devices

View File

@@ -20,7 +20,6 @@
#include "core/hle/service/aoc/aoc_u.h"
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/audio/audio.h"
#include "core/hle/service/bcat/bcat.h"
#include "core/hle/service/fatal/fatal.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/friend/friend.h"
@@ -145,12 +144,10 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
rb.Push(RESULT_SUCCESS);
return ResultCode(ErrorModule::HIPC, ErrorDescription::RemoteProcessDead);
}
case IPC::CommandType::ControlWithContext:
case IPC::CommandType::Control: {
Core::System::GetInstance().ServiceManager().InvokeControlRequest(context);
break;
}
case IPC::CommandType::RequestWithContext:
case IPC::CommandType::Request: {
InvokeRequest(context);
break;
@@ -184,7 +181,6 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
AM::InstallInterfaces(*sm, nv_flinger);
AOC::InstallInterfaces(*sm);
APM::InstallInterfaces(*sm);
BCAT::InstallInterfaces(*sm);
Audio::InstallInterfaces(*sm);
Fatal::InstallInterfaces(*sm);
FileSystem::InstallInterfaces(*sm);

View File

@@ -36,6 +36,7 @@ void GPU::WriteReg(u32 method, u32 subchannel, u32 value, u32 remaining_params)
if (method == static_cast<u32>(BufferMethods::BindObject)) {
// Bind the current subchannel to the desired engine id.
NGLOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", subchannel, value);
ASSERT(bound_engines.find(subchannel) == bound_engines.end());
bound_engines[subchannel] = static_cast<EngineID>(value);
return;
}

View File

@@ -1,4 +1,4 @@
// Copyright 2018 yuzu Emulator Project
// Copyright 2018 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -75,10 +75,6 @@ union Attribute {
enum class Index : u64 {
Position = 7,
Attribute_0 = 8,
// This attribute contains a tuple of (~, ~, InstanceId, VertexId) when inside a vertex
// shader, and a tuple of (TessCoord.x, TessCoord.y, TessCoord.z, ~) when inside a Tess Eval
// shader.
TessCoordInstanceIDVertexID = 47,
};
union {
@@ -197,11 +193,6 @@ union Instruction {
BitField<50, 1, u64> abs_d;
BitField<56, 1, u64> negate_imm;
union {
BitField<39, 3, u64> pred;
BitField<42, 1, u64> negate_pred;
} fmnmx;
float GetImm20_19() const {
float result{};
u32 imm{static_cast<u32>(imm20_19)};
@@ -319,9 +310,7 @@ public:
SHR_C,
SHR_R,
SHR_IMM,
FMNMX_C,
FMNMX_R,
FMNMX_IMM,
FMNMX,
FSETP_C, // Set Predicate
FSETP_R,
FSETP_IMM,
@@ -331,7 +320,6 @@ public:
ISETP_C,
ISETP_IMM,
ISETP_R,
PSETP,
};
enum class Type {
@@ -343,7 +331,6 @@ public:
FloatSet,
FloatSetPredicate,
IntegerSetPredicate,
PredicateSetPredicate,
Conversion,
Unknown,
};
@@ -460,9 +447,9 @@ private:
INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"),
INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
INST("0101110010010---", Id::RRO, Type::Arithmetic, "RRO"),
INST("0100110010101---", Id::F2F_C, Type::Conversion, "F2F_C"),
INST("0101110010101---", Id::F2F_R, Type::Conversion, "F2F_R"),
INST("0011100-10101---", Id::F2F_IMM, Type::Conversion, "F2F_IMM"),
INST("0100110010101---", Id::F2F_C, Type::Arithmetic, "F2F_C"),
INST("0101110010101---", Id::F2F_R, Type::Arithmetic, "F2F_R"),
INST("0011100-10101---", Id::F2F_IMM, Type::Arithmetic, "F2F_IMM"),
INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"),
INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"),
INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"),
@@ -474,9 +461,7 @@ private:
INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"),
INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"),
INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"),
INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"),
INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"),
INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
INST("0101110001100---", Id::FMNMX, Type::Arithmetic, "FMNMX"),
INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"),
@@ -492,7 +477,6 @@ private:
INST("010010110110----", Id::ISETP_C, Type::IntegerSetPredicate, "ISETP_C"),
INST("010110110110----", Id::ISETP_R, Type::IntegerSetPredicate, "ISETP_R"),
INST("0011011-0110----", Id::ISETP_IMM, Type::IntegerSetPredicate, "ISETP_IMM"),
INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"),
};
#undef INST
std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) {

View File

@@ -58,25 +58,6 @@ GPUVAddr MemoryManager::MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size)
return gpu_addr;
}
GPUVAddr MemoryManager::UnmapBuffer(GPUVAddr gpu_addr, u64 size) {
ASSERT((gpu_addr & PAGE_MASK) == 0);
for (u64 offset = 0; offset < size; offset += PAGE_SIZE) {
ASSERT(PageSlot(gpu_addr + offset) != static_cast<u64>(PageStatus::Allocated) &&
PageSlot(gpu_addr + offset) != static_cast<u64>(PageStatus::Unmapped));
PageSlot(gpu_addr + offset) = static_cast<u64>(PageStatus::Unmapped);
}
// Delete the region mappings that are contained within the unmapped region
mapped_regions.erase(std::remove_if(mapped_regions.begin(), mapped_regions.end(),
[&](const MappedRegion& region) {
return region.gpu_addr <= gpu_addr &&
region.gpu_addr + region.size < gpu_addr + size;
}),
mapped_regions.end());
return gpu_addr;
}
boost::optional<GPUVAddr> MemoryManager::FindFreeBlock(u64 size, u64 align) {
GPUVAddr gpu_addr = 0;
u64 free_space = 0;

View File

@@ -25,7 +25,6 @@ public:
GPUVAddr AllocateSpace(GPUVAddr gpu_addr, u64 size, u64 align);
GPUVAddr MapBufferEx(VAddr cpu_addr, u64 size);
GPUVAddr MapBufferEx(VAddr cpu_addr, GPUVAddr gpu_addr, u64 size);
GPUVAddr UnmapBuffer(GPUVAddr gpu_addr, u64 size);
boost::optional<VAddr> GpuToCpuAddress(GPUVAddr gpu_addr);
std::vector<GPUVAddr> CpuToGpuAddress(VAddr cpu_addr) const;

View File

@@ -75,11 +75,14 @@ RasterizerOpenGL::RasterizerOpenGL() {
// Clipping plane 0 is always enabled for PICA fixed clip plane z <= 0
state.clip_distance[0] = true;
// Generate VAO and UBO
// Generate VBO, VAO and UBO
vertex_buffer = OGLStreamBuffer::MakeBuffer(GLAD_GL_ARB_buffer_storage, GL_ARRAY_BUFFER);
vertex_buffer->Create(VERTEX_BUFFER_SIZE, VERTEX_BUFFER_SIZE / 2);
sw_vao.Create();
uniform_buffer.Create();
state.draw.vertex_array = sw_vao.handle;
state.draw.vertex_buffer = vertex_buffer->GetHandle();
state.draw.uniform_buffer = uniform_buffer.handle;
state.Apply();
@@ -87,6 +90,7 @@ RasterizerOpenGL::RasterizerOpenGL() {
framebuffer.Create();
hw_vao.Create();
hw_vao_enabled_attributes.fill(false);
stream_buffer = OGLStreamBuffer::MakeBuffer(has_ARB_buffer_storage, GL_ARRAY_BUFFER);
stream_buffer->Create(STREAM_BUFFER_SIZE, STREAM_BUFFER_SIZE / 2);
@@ -177,6 +181,8 @@ std::pair<u8*, GLintptr> RasterizerOpenGL::SetupVertexArrays(u8* array_ptr,
glVertexAttribFormat(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
attrib.IsNormalized() ? GL_TRUE : GL_FALSE, attrib.offset);
glVertexAttribBinding(index, attrib.buffer);
hw_vao_enabled_attributes[index] = true;
}
return {array_ptr, buffer_offset};

View File

@@ -134,17 +134,21 @@ private:
std::unique_ptr<GLShader::ProgramManager> shader_program_manager;
OGLVertexArray sw_vao;
OGLVertexArray hw_vao;
std::array<bool, 16> hw_vao_enabled_attributes;
std::array<SamplerInfo, GLShader::NumTextureSamplers> texture_samplers;
std::array<std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers>,
Tegra::Engines::Maxwell3D::Regs::MaxShaderStage>
ssbos;
static constexpr size_t STREAM_BUFFER_SIZE = 128 * 1024 * 1024;
std::unique_ptr<OGLStreamBuffer> stream_buffer;
static constexpr size_t VERTEX_BUFFER_SIZE = 128 * 1024 * 1024;
std::unique_ptr<OGLStreamBuffer> vertex_buffer;
OGLBuffer uniform_buffer;
OGLFramebuffer framebuffer;
static constexpr size_t STREAM_BUFFER_SIZE = 4 * 1024 * 1024;
std::unique_ptr<OGLStreamBuffer> stream_buffer;
size_t CalculateVertexArraysSize() const;
std::pair<u8*, GLintptr> SetupVertexArrays(u8* array_ptr, GLintptr buffer_offset);

View File

@@ -45,11 +45,8 @@ struct FormatTuple {
static constexpr std::array<FormatTuple, SurfaceParams::MaxPixelFormat> tex_format_tuples = {{
{GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, false}, // ABGR8
{GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, false}, // B5G6R5
{GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5_REV, false}, // B5G6R5
{GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, false}, // A2B10G10R10
{GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, false}, // A1B5G5R5
{GL_R8, GL_RED, GL_UNSIGNED_BYTE, false}, // R8
{GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT, false}, // RGBA16F
{GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT1
{GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT23
{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, true}, // DXT45
@@ -59,8 +56,8 @@ static const FormatTuple& GetFormatTuple(PixelFormat pixel_format, ComponentType
const SurfaceType type = SurfaceParams::GetFormatType(pixel_format);
if (type == SurfaceType::ColorTexture) {
ASSERT(static_cast<size_t>(pixel_format) < tex_format_tuples.size());
// For now only UNORM components are supported, or RGBA16F which is type FLOAT
ASSERT(component_type == ComponentType::UNorm || pixel_format == PixelFormat::RGBA16F);
// For now only UNORM components are supported
ASSERT(component_type == ComponentType::UNorm);
return tex_format_tuples[static_cast<unsigned int>(pixel_format)];
} else if (type == SurfaceType::Depth || type == SurfaceType::DepthStencil) {
// TODO(Subv): Implement depth formats
@@ -110,10 +107,8 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra:
SurfaceParams::MaxPixelFormat>
morton_to_gl_fns = {
MortonCopy<true, PixelFormat::ABGR8>, MortonCopy<true, PixelFormat::B5G6R5>,
MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::A1B5G5R5>,
MortonCopy<true, PixelFormat::R8>, MortonCopy<true, PixelFormat::RGBA16F>,
MortonCopy<true, PixelFormat::DXT1>, MortonCopy<true, PixelFormat::DXT23>,
MortonCopy<true, PixelFormat::DXT45>,
MortonCopy<true, PixelFormat::A2B10G10R10>, MortonCopy<true, PixelFormat::DXT1>,
MortonCopy<true, PixelFormat::DXT23>, MortonCopy<true, PixelFormat::DXT45>,
};
static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra::GPUVAddr,
@@ -123,9 +118,6 @@ static constexpr std::array<void (*)(u32, u32, u32, u8*, Tegra::GPUVAddr, Tegra:
MortonCopy<false, PixelFormat::ABGR8>,
MortonCopy<false, PixelFormat::B5G6R5>,
MortonCopy<false, PixelFormat::A2B10G10R10>,
MortonCopy<false, PixelFormat::A1B5G5R5>,
MortonCopy<false, PixelFormat::R8>,
MortonCopy<false, PixelFormat::RGBA16F>,
// TODO(Subv): Swizzling the DXT1/DXT23/DXT45 formats is not yet supported
nullptr,
nullptr,

View File

@@ -57,12 +57,9 @@ struct SurfaceParams {
ABGR8 = 0,
B5G6R5 = 1,
A2B10G10R10 = 2,
A1B5G5R5 = 3,
R8 = 4,
RGBA16F = 5,
DXT1 = 6,
DXT23 = 7,
DXT45 = 8,
DXT1 = 3,
DXT23 = 4,
DXT45 = 5,
Max,
Invalid = 255,
@@ -101,9 +98,6 @@ struct SurfaceParams {
1, // ABGR8
1, // B5G6R5
1, // A2B10G10R10
1, // A1B5G5R5
1, // R8
2, // RGBA16F
4, // DXT1
4, // DXT23
4, // DXT45
@@ -124,9 +118,6 @@ struct SurfaceParams {
32, // ABGR8
16, // B5G6R5
32, // A2B10G10R10
16, // A1B5G5R5
8, // R8
64, // RGBA16F
64, // DXT1
128, // DXT23
128, // DXT45
@@ -142,12 +133,9 @@ struct SurfaceParams {
static PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format) {
switch (format) {
case Tegra::RenderTargetFormat::RGBA8_UNORM:
case Tegra::RenderTargetFormat::RGBA8_SRGB:
return PixelFormat::ABGR8;
case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
return PixelFormat::A2B10G10R10;
case Tegra::RenderTargetFormat::RGBA16_FLOAT:
return PixelFormat::RGBA16F;
default:
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
UNREACHABLE();
@@ -173,12 +161,6 @@ struct SurfaceParams {
return PixelFormat::B5G6R5;
case Tegra::Texture::TextureFormat::A2B10G10R10:
return PixelFormat::A2B10G10R10;
case Tegra::Texture::TextureFormat::A1B5G5R5:
return PixelFormat::A1B5G5R5;
case Tegra::Texture::TextureFormat::R8:
return PixelFormat::R8;
case Tegra::Texture::TextureFormat::R16_G16_B16_A16:
return PixelFormat::RGBA16F;
case Tegra::Texture::TextureFormat::DXT1:
return PixelFormat::DXT1;
case Tegra::Texture::TextureFormat::DXT23:
@@ -200,12 +182,6 @@ struct SurfaceParams {
return Tegra::Texture::TextureFormat::B5G6R5;
case PixelFormat::A2B10G10R10:
return Tegra::Texture::TextureFormat::A2B10G10R10;
case PixelFormat::A1B5G5R5:
return Tegra::Texture::TextureFormat::A1B5G5R5;
case PixelFormat::R8:
return Tegra::Texture::TextureFormat::R8;
case PixelFormat::RGBA16F:
return Tegra::Texture::TextureFormat::R16_G16_B16_A16;
case PixelFormat::DXT1:
return Tegra::Texture::TextureFormat::DXT1;
case PixelFormat::DXT23:
@@ -232,11 +208,8 @@ struct SurfaceParams {
// TODO(Subv): Implement more render targets
switch (format) {
case Tegra::RenderTargetFormat::RGBA8_UNORM:
case Tegra::RenderTargetFormat::RGBA8_SRGB:
case Tegra::RenderTargetFormat::RGB10_A2_UNORM:
return ComponentType::UNorm;
case Tegra::RenderTargetFormat::RGBA16_FLOAT:
return ComponentType::Float;
default:
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
UNREACHABLE();

View File

@@ -299,7 +299,7 @@ public:
* are stored as floats, so this may require conversion.
* @param reg The destination register to use.
* @param elem The element to use for the operation.
* @param attribute The input attribute to use as the source value.
* @param attribute The input attibute to use as the source value.
*/
void SetRegisterToInputAttibute(const Register& reg, u64 elem, Attribute::Index attribute) {
std::string dest = GetRegisterAsFloat(reg);
@@ -451,12 +451,6 @@ private:
switch (attribute) {
case Attribute::Index::Position:
return "position";
case Attribute::Index::TessCoordInstanceIDVertexID:
// TODO(Subv): Find out what the values are for the first two elements when inside a
// vertex shader, and what's the value of the fourth element when inside a Tess Eval
// shader.
ASSERT(stage == Maxwell3D::Regs::ShaderStage::Vertex);
return "vec4(0, 0, gl_InstanceID, gl_VertexID)";
default:
const u32 index{static_cast<u32>(attribute) -
static_cast<u32>(Attribute::Index::Attribute_0)};
@@ -586,62 +580,20 @@ private:
* @param instr Instruction to generate the if condition for.
* @returns string containing the predicate condition.
*/
std::string GetPredicateCondition(u64 index, bool negate) const {
std::string GetPredicateCondition(Instruction instr) const {
using Tegra::Shader::Pred;
std::string variable;
ASSERT(instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex));
// Index 7 is used as an 'Always True' condition.
if (index == static_cast<u64>(Pred::UnusedIndex))
variable = "true";
else
variable = 'p' + std::to_string(index);
std::string variable =
'p' + std::to_string(static_cast<u64>(instr.pred.pred_index.Value()));
if (negate) {
if (instr.negate_pred) {
return "!(" + variable + ')';
}
return variable;
}
/**
* Returns the comparison string to use to compare two values in the 'set' family of
* instructions.
* @params condition The condition used in the 'set'-family instruction.
* @returns String corresponding to the GLSL operator that matches the desired comparison.
*/
std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const {
using Tegra::Shader::PredCondition;
static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = {
{PredCondition::LessThan, "<"}, {PredCondition::Equal, "=="},
{PredCondition::LessEqual, "<="}, {PredCondition::GreaterThan, ">"},
{PredCondition::GreaterEqual, ">="},
};
auto comparison = PredicateComparisonStrings.find(condition);
ASSERT_MSG(comparison != PredicateComparisonStrings.end(),
"Unknown predicate comparison operation");
return comparison->second;
}
/**
* Returns the operator string to use to combine two predicates in the 'setp' family of
* instructions.
* @params operation The operator used in the 'setp'-family instruction.
* @returns String corresponding to the GLSL operator that matches the desired operator.
*/
std::string GetPredicateCombiner(Tegra::Shader::PredOperation operation) const {
using Tegra::Shader::PredOperation;
static const std::unordered_map<PredOperation, const char*> PredicateOperationStrings = {
{PredOperation::And, "&&"},
{PredOperation::Or, "||"},
{PredOperation::Xor, "^^"},
};
auto op = PredicateOperationStrings.find(operation);
ASSERT_MSG(op != PredicateOperationStrings.end(), "Unknown predicate operation");
return op->second;
}
/*
* Returns whether the instruction at the specified offset is a 'sched' instruction.
* Sched instructions always appear before a sequence of 3 instructions.
@@ -682,9 +634,7 @@ private:
"NeverExecute predicate not implemented");
if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
shader.AddLine("if (" +
GetPredicateCondition(instr.pred.pred_index, instr.negate_pred != 0) +
')');
shader.AddLine("if (" + GetPredicateCondition(instr) + ')');
shader.AddLine('{');
++shader.scope;
}
@@ -780,18 +730,6 @@ private:
}
break;
}
case OpCode::Id::FMNMX_C:
case OpCode::Id::FMNMX_R:
case OpCode::Id::FMNMX_IMM: {
std::string condition =
GetPredicateCondition(instr.alu.fmnmx.pred, instr.alu.fmnmx.negate_pred != 0);
std::string parameters = op_a + ',' + op_b;
regs.SetRegisterToFloat(instr.gpr0, 0,
'(' + condition + ") ? min(" + parameters + ") : max(" +
parameters + ')',
1, 1);
break;
}
case OpCode::Id::RRO: {
NGLOG_DEBUG(HW_GPU, "Skipping RRO instruction");
break;
@@ -840,14 +778,13 @@ private:
}
case OpCode::Type::Conversion: {
ASSERT_MSG(instr.conversion.size == Register::Size::Word, "Unimplemented");
ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
ASSERT_MSG(!instr.conversion.negate_a, "Unimplemented");
ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented");
switch (opcode->GetId()) {
case OpCode::Id::I2I_R:
case OpCode::Id::I2F_R: {
ASSERT_MSG(!instr.conversion.selector, "Unimplemented");
std::string op_a =
regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed);
@@ -858,16 +795,6 @@ private:
regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1);
break;
}
case OpCode::Id::F2F_R: {
std::string op_a = regs.GetRegisterAsFloat(instr.gpr20);
if (instr.conversion.abs_a) {
op_a = "abs(" + op_a + ')';
}
regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1);
break;
}
default: {
NGLOG_CRITICAL(HW_GPU, "Unhandled conversion instruction: {}", opcode->GetName());
UNREACHABLE();
@@ -946,25 +873,28 @@ private:
}
using Tegra::Shader::Pred;
ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) &&
instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex),
"Compound predicates are not implemented");
// We can't use the constant predicate as destination.
ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex));
std::string second_pred =
GetPredicateCondition(instr.fsetp.pred39, instr.fsetp.neg_pred != 0);
std::string comparator = GetPredicateComparison(instr.fsetp.cond);
std::string combiner = GetPredicateCombiner(instr.fsetp.op);
std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')';
// Set the primary predicate to the result of Predicate OP SecondPredicate
SetPredicate(instr.fsetp.pred3,
'(' + predicate + ") " + combiner + " (" + second_pred + ')');
if (instr.fsetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) {
// Set the secondary predicate to the result of !Predicate OP SecondPredicate, if
// enabled
SetPredicate(instr.fsetp.pred0,
"!(" + predicate + ") " + combiner + " (" + second_pred + ')');
using Tegra::Shader::PredCondition;
switch (instr.fsetp.cond) {
case PredCondition::LessThan:
SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')');
break;
case PredCondition::Equal:
SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')');
break;
case PredCondition::LessEqual:
SetPredicate(instr.fsetp.pred3, '(' + op_a + ") <= (" + op_b + ')');
break;
default:
NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b);
UNREACHABLE();
}
break;
}
@@ -996,18 +926,35 @@ private:
op_b = "abs(" + op_b + ')';
}
using Tegra::Shader::Pred;
ASSERT_MSG(instr.fset.pred39 == static_cast<u64>(Pred::UnusedIndex),
"Compound predicates are not implemented");
// The fset instruction sets a register to 1.0 if the condition is true, and to 0
// otherwise.
std::string second_pred =
GetPredicateCondition(instr.fset.pred39, instr.fset.neg_pred != 0);
std::string comparator = GetPredicateComparison(instr.fset.cond);
std::string combiner = GetPredicateCombiner(instr.fset.op);
std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " +
combiner + " (" + second_pred + "))";
regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1);
using Tegra::Shader::PredCondition;
switch (instr.fset.cond) {
case PredCondition::LessThan:
regs.SetRegisterToFloat(instr.gpr0, 0,
"((" + op_a + ") < (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
case PredCondition::Equal:
regs.SetRegisterToFloat(instr.gpr0, 0,
"((" + op_a + ") == (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
case PredCondition::LessEqual:
regs.SetRegisterToFloat(instr.gpr0, 0,
"((" + op_a + ") <= (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
case PredCondition::GreaterThan:
regs.SetRegisterToFloat(instr.gpr0, 0,
"((" + op_a + ") > (" + op_b + ")) ? 1.0 : 0", 1, 1);
break;
default:
NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})",
static_cast<unsigned>(instr.fset.cond.Value()), op_a, op_b);
UNREACHABLE();
}
break;
}
default: {

View File

@@ -4,7 +4,6 @@
#pragma once
#include <string>
#include <vector>
#include <glad/glad.h>
#include "common/assert.h"
@@ -12,27 +11,6 @@
namespace GLShader {
/**
* Utility function to log the source code of a list of shaders.
* @param shaders The OpenGL shaders whose source we will print.
*/
template <typename... T>
void LogShaderSource(T... shaders) {
auto shader_list = {shaders...};
for (const auto& shader : shader_list) {
if (shader == 0)
continue;
GLint source_length;
glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &source_length);
std::string source(source_length, ' ');
glGetShaderSource(shader, source_length, nullptr, &source[0]);
NGLOG_INFO(Render_OpenGL, "Shader source {}", source);
}
}
/**
* Utility function to create and compile an OpenGL GLSL shader
* @param source String of the GLSL shader program
@@ -77,11 +55,6 @@ GLuint LoadProgram(bool separable_program, T... shaders) {
}
}
if (result == GL_FALSE) {
// There was a problem linking the shader, print the source for debugging purposes.
LogShaderSource(shaders...);
}
ASSERT_MSG(result == GL_TRUE, "Shader not linked");
((shaders == 0 ? (void)0 : glDetachShader(program_id, shaders)), ...);

View File

@@ -55,13 +55,8 @@ u32 BytesPerPixel(TextureFormat format) {
case TextureFormat::A8R8G8B8:
case TextureFormat::A2B10G10R10:
return 4;
case TextureFormat::A1B5G5R5:
case TextureFormat::B5G6R5:
return 2;
case TextureFormat::R8:
return 1;
case TextureFormat::R16_G16_B16_A16:
return 8;
default:
UNIMPLEMENTED_MSG("Format not implemented");
break;
@@ -85,10 +80,7 @@ std::vector<u8> UnswizzleTexture(VAddr address, TextureFormat format, u32 width,
break;
case TextureFormat::A8R8G8B8:
case TextureFormat::A2B10G10R10:
case TextureFormat::A1B5G5R5:
case TextureFormat::B5G6R5:
case TextureFormat::R8:
case TextureFormat::R16_G16_B16_A16:
CopySwizzledData(width, height, bytes_per_pixel, bytes_per_pixel, data,
unswizzled_data.data(), true, block_height);
break;
@@ -111,9 +103,7 @@ std::vector<u8> DecodeTexture(const std::vector<u8>& texture_data, TextureFormat
case TextureFormat::DXT45:
case TextureFormat::A8R8G8B8:
case TextureFormat::A2B10G10R10:
case TextureFormat::A1B5G5R5:
case TextureFormat::B5G6R5:
case TextureFormat::R8:
// TODO(Subv): For the time being just forward the same data without any decoding.
rgba_data = texture_data;
break;

View File

@@ -14,82 +14,12 @@ namespace Tegra {
namespace Texture {
enum class TextureFormat : u32 {
R32_G32_B32_A32 = 0x01,
R32_G32_B32 = 0x02,
R16_G16_B16_A16 = 0x03,
R32_G32 = 0x04,
R32_B24G8 = 0x05,
ETC2_RGB = 0x06,
X8B8G8R8 = 0x07,
A8R8G8B8 = 0x08,
A2B10G10R10 = 0x09,
ETC2_RGB_PTA = 0x0a,
ETC2_RGBA = 0x0b,
R16_G16 = 0x0c,
G8R24 = 0x0d,
G24R8 = 0x0e,
R32 = 0x0f,
BC6H_SF16 = 0x10,
BC6H_UF16 = 0x11,
A4B4G4R4 = 0x12,
A5B5G5R1 = 0x13,
A1B5G5R5 = 0x14,
A8R8G8B8 = 0x8,
A2B10G10R10 = 0x9,
B5G6R5 = 0x15,
B6G5R5 = 0x16,
BC7U = 0x17,
G8R8 = 0x18,
EAC = 0x19,
EACX2 = 0x1a,
R16 = 0x1b,
Y8_VIDEO = 0x1c,
R8 = 0x1d,
G4R4 = 0x1e,
R1 = 0x1f,
E5B9G9R9_SHAREDEXP = 0x20,
BF10GF11RF11 = 0x21,
G8B8G8R8 = 0x22,
B8G8R8G8 = 0x23,
DXT1 = 0x24,
DXT23 = 0x25,
DXT45 = 0x26,
DXN1 = 0x27,
DXN2 = 0x28,
Z24S8 = 0x29,
X8Z24 = 0x2a,
S8Z24 = 0x2b,
X4V4Z24__COV4R4V = 0x2c,
X4V4Z24__COV8R8V = 0x2d,
V8Z24__COV4R12V = 0x2e,
ZF32 = 0x2f,
ZF32_X24S8 = 0x30,
X8Z24_X20V4S8__COV4R4V = 0x31,
X8Z24_X20V4S8__COV8R8V = 0x32,
ZF32_X20V4X8__COV4R4V = 0x33,
ZF32_X20V4X8__COV8R8V = 0x34,
ZF32_X20V4S8__COV4R4V = 0x35,
ZF32_X20V4S8__COV8R8V = 0x36,
X8Z24_X16V8S8__COV4R12V = 0x37,
ZF32_X16V8X8__COV4R12V = 0x38,
ZF32_X16V8S8__COV4R12V = 0x39,
Z16 = 0x3a,
V8Z24__COV8R24V = 0x3b,
X8Z24_X16V8S8__COV8R24V = 0x3c,
ZF32_X16V8X8__COV8R24V = 0x3d,
ZF32_X16V8S8__COV8R24V = 0x3e,
ASTC_2D_4X4 = 0x40,
ASTC_2D_5X5 = 0x41,
ASTC_2D_6X6 = 0x42,
ASTC_2D_8X8 = 0x44,
ASTC_2D_10X10 = 0x45,
ASTC_2D_12X12 = 0x46,
ASTC_2D_5X4 = 0x50,
ASTC_2D_6X5 = 0x51,
ASTC_2D_8X6 = 0x52,
ASTC_2D_10X8 = 0x53,
ASTC_2D_12X10 = 0x54,
ASTC_2D_8X5 = 0x55,
ASTC_2D_10X5 = 0x56,
ASTC_2D_10X6 = 0x57,
};
enum class TextureType : u32 {

View File

@@ -98,30 +98,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeMutexInfo::GetChildren() cons
return list;
}
WaitTreeCallstack::WaitTreeCallstack(const Kernel::Thread& thread) : thread(thread) {}
QString WaitTreeCallstack::GetText() const {
return tr("Call stack");
}
std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeCallstack::GetChildren() const {
std::vector<std::unique_ptr<WaitTreeItem>> list;
constexpr size_t BaseRegister = 29;
u64 base_pointer = thread.context.cpu_registers[BaseRegister];
while (base_pointer != 0) {
u64 lr = Memory::Read64(base_pointer + sizeof(u64));
if (lr == 0)
break;
list.push_back(
std::make_unique<WaitTreeText>(tr("0x%1").arg(lr - sizeof(u32), 16, 16, QChar('0'))));
base_pointer = Memory::Read64(base_pointer);
}
return list;
}
WaitTreeWaitObject::WaitTreeWaitObject(const Kernel::WaitObject& o) : object(o) {}
bool WaitTreeExpandableItem::IsExpandable() const {
@@ -293,8 +269,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
thread.IsSleepingOnWaitAll()));
}
list.push_back(std::make_unique<WaitTreeCallstack>(thread));
return list;
}

View File

@@ -73,17 +73,6 @@ private:
Kernel::SharedPtr<Kernel::Thread> owner;
};
class WaitTreeCallstack : public WaitTreeExpandableItem {
Q_OBJECT
public:
explicit WaitTreeCallstack(const Kernel::Thread& thread);
QString GetText() const override;
std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
private:
const Kernel::Thread& thread;
};
class WaitTreeWaitObject : public WaitTreeExpandableItem {
Q_OBJECT
public:

View File

@@ -7,19 +7,8 @@
#include <string>
#include <thread>
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
// This needs to be included before getopt.h because the latter #defines symbols used by it
#include "common/microprofile.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/gdbstub/gdbstub.h"
#include "core/loader/loader.h"
#include "core/settings.h"
#include "yuzu_cmd/config.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
#ifdef _MSC_VER
#include <getopt.h>
@@ -35,6 +24,19 @@
#include <shellapi.h>
#endif
#include "common/logging/backend.h"
#include "common/logging/filter.h"
#include "common/logging/log.h"
#include "common/scm_rev.h"
#include "common/scope_exit.h"
#include "common/string_util.h"
#include "core/core.h"
#include "core/gdbstub/gdbstub.h"
#include "core/loader/loader.h"
#include "core/settings.h"
#include "yuzu_cmd/config.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
#ifdef _WIN32
extern "C" {
// tells Nvidia and AMD drivers to use the dedicated GPU by default on laptops with switchable