Compare commits

..

21 Commits

Author SHA1 Message Date
kmather73
b56dcacf2d Merge branch 'master' of https://github.com/yuzu-emu/yuzu into u/kemathe/GPU-puller 2018-12-28 18:04:21 -08:00
kmather73
d0600bc029 Fix clang error 2018-12-28 15:45:51 -08:00
kmather73
574ce43406 Set up the regs and regs_assert_positions up properly 2018-12-28 15:41:31 -08:00
kmather73
624f21f859 Remove local var 2018-12-28 00:41:42 -08:00
kmather73
08b484b11e union magic refcnt as well 2018-12-28 00:23:19 -08:00
kmather73
6574bbbbda More union magic for setting regs value. 2018-12-28 00:13:49 -08:00
kmather73
b1339327a9 Removing unused funcitons and other pr comment 2018-12-27 23:13:24 -08:00
kmather73
459dcffee7 Removing unused funcitons and other pr comment 2018-12-27 21:01:29 -08:00
kmather73
1ddb570250 White space clang error 2018-12-26 17:06:46 -08:00
kmather73
9cb18798be Fix clang style issues 2018-12-26 15:14:24 -08:00
kmather73
ca9203b847 Updated to use Memory::WriteBlock instead of Memory::Write* 2018-12-26 15:10:37 -08:00
kmather73
a6b8baaff3 Move puller members into the regs union 2018-12-26 14:26:50 -08:00
kmather73
3e84c12de4 two more white spaces for the Clang formatting. 2018-12-16 23:37:55 -08:00
kmather73
f13c6a480a More clang formatting. 2018-12-16 23:32:17 -08:00
kmather73
e90c0a41a6 Fix the clang-format issues. 2018-12-16 23:21:50 -08:00
kmather73
3446f72f08 Forgot to remove GpuSmaphoreAddress union. 2018-12-16 18:57:08 -08:00
kmather73
2f7712ebc2 Update for comments. Added ReferenceCount method 2018-12-16 18:45:07 -08:00
kmather73
43a8354eaa Fix style. 2018-12-16 01:48:18 -08:00
kmather73
5ce2f715ce Nit: Add Break to default case. 2018-12-16 01:15:20 -08:00
kmather73
73708f4582 Nit: Fix 2 style issues 2018-12-16 01:08:49 -08:00
kmather73
7ff68f6588 Implemented the puller semaphore operations. 2018-12-16 00:59:57 -08:00
45 changed files with 524 additions and 529 deletions

2
externals/fmt vendored

View File

@@ -1,6 +1,5 @@
add_library(core STATIC
arm/arm_interface.h
arm/arm_interface.cpp
arm/exclusive_monitor.cpp
arm/exclusive_monitor.h
arm/unicorn/arm_unicorn.cpp

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.
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/arm/arm_interface.h"
#include "core/memory.h"
namespace Core {
void ARM_Interface::LogBacktrace() const {
VAddr fp = GetReg(29);
VAddr lr = GetReg(30);
const VAddr sp = GetReg(13);
const VAddr pc = GetPC();
LOG_ERROR(Core_ARM, "Backtrace, sp={:016X}, pc={:016X}", sp, pc);
while (true) {
LOG_ERROR(Core_ARM, "{:016X}", lr);
if (!fp) {
break;
}
lr = Memory::Read64(fp + 8) - 4;
fp = Memory::Read64(fp);
}
}
} // namespace Core

View File

@@ -141,14 +141,6 @@ public:
/// Prepare core for thread reschedule (if needed to correctly handle state)
virtual void PrepareReschedule() = 0;
/// fp (= r29) points to the last frame record.
/// Note that this is the frame record for the *previous* frame, not the current one.
/// Note we need to subtract 4 from our last read to get the proper address
/// Frame records are two words long:
/// fp+0 : pointer to previous frame record
/// fp+8 : value of lr for frame
void LogBacktrace() const;
};
} // namespace Core

View File

@@ -10,7 +10,6 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/svc.h"
#include "core/memory.h"
namespace Core {

View File

@@ -18,7 +18,7 @@
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/server_port.h"
namespace IPC {

View File

@@ -8,7 +8,6 @@
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/session.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/result.h"
namespace Kernel {

View File

@@ -6,9 +6,9 @@
#include <memory>
#include <string>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
union ResultCode;
#include "core/hle/result.h"
namespace Kernel {

View File

@@ -22,16 +22,11 @@
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
#include "core/memory.h"
namespace Kernel {
SessionRequestHandler::SessionRequestHandler() = default;
SessionRequestHandler::~SessionRequestHandler() = default;
void SessionRequestHandler::ClientConnected(SharedPtr<ServerSession> server_session) {
server_session->SetHleHandler(shared_from_this());
connected_sessions.push_back(std::move(server_session));

View File

@@ -14,6 +14,8 @@
#include "common/swap.h"
#include "core/hle/ipc.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/thread.h"
namespace Service {
class ServiceFrameworkBase;
@@ -25,13 +27,9 @@ class Domain;
class HandleTable;
class HLERequestContext;
class Process;
class ServerSession;
class Thread;
class ReadableEvent;
class WritableEvent;
enum class ThreadWakeupReason;
/**
* Interface implemented by HLE Session handlers.
* This can be provided to a ServerSession in order to hook into several relevant events
@@ -39,8 +37,7 @@ enum class ThreadWakeupReason;
*/
class SessionRequestHandler : public std::enable_shared_from_this<SessionRequestHandler> {
public:
SessionRequestHandler();
virtual ~SessionRequestHandler();
virtual ~SessionRequestHandler() = default;
/**
* Handles a sync request from the emulated application.

View File

@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <array>
#include <atomic>
#include <memory>
#include <mutex>

View File

@@ -20,35 +20,6 @@
#include "core/settings.h"
namespace Kernel {
namespace {
/**
* Sets up the primary application thread
*
* @param owner_process The parent process for the main thread
* @param kernel The kernel instance to create the main thread under.
* @param entry_point The address at which the thread should start execution
* @param priority The priority to give the main thread
*/
void SetupMainThread(Process& owner_process, KernelCore& kernel, VAddr entry_point, u32 priority) {
// Setup page table so we can write to memory
SetCurrentPageTable(&owner_process.VMManager().page_table);
// Initialize new "main" thread
const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0,
owner_process.GetIdealCore(), stack_top, owner_process);
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
// Register 1 must be a handle to the main thread
const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
thread->SetGuestHandle(guest_handle);
thread->GetContext().cpu_registers[1] = guest_handle;
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
thread->ResumeFromWait();
}
} // Anonymous namespace
CodeSet::CodeSet() = default;
CodeSet::~CodeSet() = default;
@@ -93,7 +64,7 @@ ResultCode Process::ClearSignalState() {
ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
program_id = metadata.GetTitleID();
ideal_core = metadata.GetMainThreadCore();
ideal_processor = metadata.GetMainThreadCore();
is_64bit_process = metadata.Is64BitProgram();
vm_manager.Reset(metadata.GetAddressSpaceType());
@@ -115,7 +86,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
vm_manager.LogLayout();
ChangeStatus(ProcessStatus::Running);
SetupMainThread(*this, kernel, entry_point, main_thread_priority);
Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this);
}
void Process::PrepareForTermination() {

View File

@@ -14,6 +14,7 @@
#include "common/common_types.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/process_capability.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/vm_manager.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"
@@ -26,7 +27,6 @@ namespace Kernel {
class KernelCore;
class ResourceLimit;
class Thread;
struct AddressMapping {
// Address and size must be page-aligned
@@ -168,18 +168,18 @@ public:
/// Gets the resource limit descriptor for this process
SharedPtr<ResourceLimit> GetResourceLimit() const;
/// Gets the ideal CPU core ID for this process
u8 GetIdealCore() const {
return ideal_core;
/// Gets the default CPU ID for this process
u8 GetDefaultProcessorID() const {
return ideal_processor;
}
/// Gets the bitmask of allowed cores that this process' threads can run on.
u64 GetCoreMask() const {
/// Gets the bitmask of allowed CPUs that this process' threads can run on.
u64 GetAllowedProcessorMask() const {
return capabilities.GetCoreMask();
}
/// Gets the bitmask of allowed thread priorities.
u64 GetPriorityMask() const {
u64 GetAllowedThreadPriorityMask() const {
return capabilities.GetPriorityMask();
}
@@ -280,8 +280,8 @@ private:
/// Resource limit descriptor for this process
SharedPtr<ResourceLimit> resource_limit;
/// The ideal CPU core for this process, threads are scheduled on this core by default.
u8 ideal_core = 0;
/// The default CPU for this process, threads are scheduled on this cpu by default.
u8 ideal_processor = 0;
u32 is_virtual_address_memory_enabled = 0;
/// The Thread Local Storage area is allocated as processes create threads,

View File

@@ -6,7 +6,6 @@
#include <utility>
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/ipc_helpers.h"

View File

@@ -8,6 +8,7 @@
#include <string>
#include <vector>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
#include "core/hle/result.h"

View File

@@ -684,9 +684,6 @@ static void Break(u32 reason, u64 info1, u64 info2) {
"Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
reason, info1, info2);
handle_debug_buffer(info1, info2);
Core::System::GetInstance()
.ArmInterface(static_cast<std::size_t>(GetCurrentThread()->GetProcessorID()))
.LogBacktrace();
ASSERT(false);
Core::CurrentProcess()->PrepareForTermination();
@@ -715,8 +712,8 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
enum class GetInfoType : u64 {
// 1.0.0+
AllowedCPUCoreMask = 0,
AllowedThreadPriorityMask = 1,
AllowedCpuIdBitmask = 0,
AllowedThreadPrioBitmask = 1,
MapRegionBaseAddr = 2,
MapRegionSize = 3,
HeapRegionBaseAddr = 4,
@@ -747,8 +744,8 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
const auto info_id_type = static_cast<GetInfoType>(info_id);
switch (info_id_type) {
case GetInfoType::AllowedCPUCoreMask:
case GetInfoType::AllowedThreadPriorityMask:
case GetInfoType::AllowedCpuIdBitmask:
case GetInfoType::AllowedThreadPrioBitmask:
case GetInfoType::MapRegionBaseAddr:
case GetInfoType::MapRegionSize:
case GetInfoType::HeapRegionBaseAddr:
@@ -774,12 +771,12 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
}
switch (info_id_type) {
case GetInfoType::AllowedCPUCoreMask:
*result = process->GetCoreMask();
case GetInfoType::AllowedCpuIdBitmask:
*result = process->GetAllowedProcessorMask();
return RESULT_SUCCESS;
case GetInfoType::AllowedThreadPriorityMask:
*result = process->GetPriorityMask();
case GetInfoType::AllowedThreadPrioBitmask:
*result = process->GetAllowedThreadPriorityMask();
return RESULT_SUCCESS;
case GetInfoType::MapRegionBaseAddr:
@@ -1219,37 +1216,31 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
"threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}",
entry_point, arg, stack_top, priority, processor_id, *out_handle);
if (priority > THREADPRIO_LOWEST) {
LOG_ERROR(Kernel_SVC, "An invalid priority was specified, expected {} but got {}",
THREADPRIO_LOWEST, priority);
return ERR_INVALID_THREAD_PRIORITY;
}
auto* const current_process = Core::CurrentProcess();
if (processor_id == THREADPROCESSORID_IDEAL) {
// Set the target CPU to the one specified by the process.
processor_id = current_process->GetIdealCore();
ASSERT(processor_id != THREADPROCESSORID_IDEAL);
if (processor_id == THREADPROCESSORID_DEFAULT) {
// Set the target CPU to the one specified in the process' exheader.
processor_id = current_process->GetDefaultProcessorID();
ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
}
if (processor_id < THREADPROCESSORID_0 || processor_id > THREADPROCESSORID_3) {
switch (processor_id) {
case THREADPROCESSORID_0:
case THREADPROCESSORID_1:
case THREADPROCESSORID_2:
case THREADPROCESSORID_3:
break;
default:
LOG_ERROR(Kernel_SVC, "Invalid thread processor ID: {}", processor_id);
return ERR_INVALID_PROCESSOR_ID;
}
const u64 core_mask = current_process->GetCoreMask();
if ((core_mask | (1ULL << processor_id)) != core_mask) {
LOG_ERROR(Kernel_SVC, "Invalid thread core specified ({})", processor_id);
return ERR_INVALID_PROCESSOR_ID;
}
if (priority > THREADPRIO_LOWEST) {
LOG_ERROR(Kernel_SVC,
"Invalid thread priority specified ({}). Must be within the range 0-64",
priority);
return ERR_INVALID_THREAD_PRIORITY;
}
if (((1ULL << priority) & current_process->GetPriorityMask()) == 0) {
LOG_ERROR(Kernel_SVC, "Invalid thread priority specified ({})", priority);
return ERR_INVALID_THREAD_PRIORITY;
}
const std::string name = fmt::format("thread-{:X}", entry_point);
auto& kernel = Core::System::GetInstance().Kernel();
CASCADE_RESULT(SharedPtr<Thread> thread,
@@ -1645,13 +1636,13 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
return ERR_INVALID_HANDLE;
}
if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) {
const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore();
if (core == static_cast<u32>(THREADPROCESSORID_DEFAULT)) {
const u8 default_processor_id = thread->GetOwnerProcess()->GetDefaultProcessorID();
ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL));
ASSERT(default_processor_id != static_cast<u8>(THREADPROCESSORID_DEFAULT));
// Set the target CPU to the ideal core specified by the process.
core = ideal_cpu_core;
// Set the target CPU to the one specified in the process' exheader.
core = default_processor_id;
mask = 1ULL << core;
}

View File

@@ -12,6 +12,7 @@
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "common/math_util.h"
#include "common/thread_queue_list.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
@@ -231,6 +232,29 @@ void Thread::BoostPriority(u32 priority) {
current_priority = priority;
}
SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
Process& owner_process) {
// Setup page table so we can write to memory
SetCurrentPageTable(&owner_process.VMManager().page_table);
// Initialize new "main" thread
const VAddr stack_top = owner_process.VMManager().GetTLSIORegionEndAddress();
auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0,
stack_top, owner_process);
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
// Register 1 must be a handle to the main thread
const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
thread->SetGuestHandle(guest_handle);
thread->GetContext().cpu_registers[1] = guest_handle;
// Threads by default are dormant, wake up the main thread so it runs when the scheduler fires
thread->ResumeFromWait();
return thread;
}
void Thread::SetWaitSynchronizationResult(ResultCode result) {
context.cpu_registers[0] = result.raw;
}

View File

@@ -30,12 +30,12 @@ enum ThreadPriority : u32 {
};
enum ThreadProcessorId : s32 {
THREADPROCESSORID_IDEAL = -2, ///< Run thread on the ideal core specified by the process.
THREADPROCESSORID_0 = 0, ///< Run thread on core 0
THREADPROCESSORID_1 = 1, ///< Run thread on core 1
THREADPROCESSORID_2 = 2, ///< Run thread on core 2
THREADPROCESSORID_3 = 3, ///< Run thread on core 3
THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
THREADPROCESSORID_DEFAULT = -2, ///< Run thread on default core specified by exheader
THREADPROCESSORID_0 = 0, ///< Run thread on core 0
THREADPROCESSORID_1 = 1, ///< Run thread on core 1
THREADPROCESSORID_2 = 2, ///< Run thread on core 2
THREADPROCESSORID_3 = 3, ///< Run thread on core 3
THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this
/// Allowed CPU mask
THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) |
@@ -455,6 +455,17 @@ private:
ThreadActivity activity = ThreadActivity::Normal;
};
/**
* Sets up the primary application thread
* @param kernel The kernel instance to create the main thread under.
* @param entry_point The address at which the thread should start execution
* @param priority The priority to give the main thread
* @param owner_process The parent process for the main thread
* @return A shared pointer to the main thread
*/
SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
Process& owner_process);
/**
* Gets the current thread
*/

View File

@@ -4,11 +4,11 @@
#include <algorithm>
#include "common/assert.h"
#include "common/common_types.h"
#include "common/logging/log.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
namespace Kernel {

View File

@@ -6,6 +6,7 @@
#include <vector>
#include <boost/smart_ptr/intrusive_ptr.hpp>
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
namespace Kernel {

View File

@@ -4,7 +4,9 @@
#pragma once
#include "common/common_types.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/wait_object.h"
namespace Kernel {

View File

@@ -6,7 +6,7 @@
#include "common/assert.h"
#include "core/core.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/server_session.h"
#include "core/hle/kernel/server_port.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applets.h"

View File

@@ -7,7 +7,7 @@
#include <memory>
#include <queue>
#include "common/swap.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/writable_event.h"
union ResultCode;

View File

@@ -111,8 +111,7 @@ static void GenerateErrorReport(ResultCode error_code, const FatalInfo& info) {
}
static void ThrowFatalError(ResultCode error_code, FatalType fatal_type, const FatalInfo& info) {
LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code 0x{:X}",
static_cast<u32>(fatal_type), error_code.raw);
LOG_ERROR(Service_Fatal, "Threw fatal error type {}", static_cast<u32>(fatal_type));
switch (fatal_type) {
case FatalType::ErrorReportAndScreen:
GenerateErrorReport(error_code, info);

View File

@@ -9,9 +9,9 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/lock.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"

View File

@@ -166,7 +166,7 @@ Layer::~Layer() = default;
Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) {
auto& kernel = Core::System::GetInstance().Kernel();
vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky,
vsync_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Pulse,
fmt::format("Display VSync Event {}", id));
}

View File

@@ -264,12 +264,14 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called");
IPC::RequestParser rp{ctx};
const auto initial_type = rp.PopRaw<u8>();
auto unknown_u8 = rp.PopRaw<u8>();
ClockSnapshot clock_snapshot{};
const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>(
std::chrono::system_clock::now().time_since_epoch())
.count()};
CalendarTime calendar_time{};
const std::time_t time(time_since_epoch);
const std::tm* tm = std::localtime(&time);
if (tm == nullptr) {
@@ -278,19 +280,16 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
rb.Push(ResultCode(-1)); // TODO(ogniK): Find appropriate error code
return;
}
SteadyClockTimePoint steady_clock_time_point{CoreTiming::cyclesToMs(CoreTiming::GetTicks()) /
1000};
const SteadyClockTimePoint steady_clock_time_point{
CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / 1000, {}};
CalendarTime calendar_time{};
LocationName location_name{"UTC"};
calendar_time.year = tm->tm_year + 1900;
calendar_time.month = tm->tm_mon + 1;
calendar_time.day = tm->tm_mday;
calendar_time.hour = tm->tm_hour;
calendar_time.minute = tm->tm_min;
calendar_time.second = tm->tm_sec;
ClockSnapshot clock_snapshot{};
clock_snapshot.system_posix_time = time_since_epoch;
clock_snapshot.network_posix_time = time_since_epoch;
clock_snapshot.system_calendar_time = calendar_time;
@@ -303,10 +302,9 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
clock_snapshot.network_calendar_info = additional_info;
clock_snapshot.steady_clock_timepoint = steady_clock_time_point;
clock_snapshot.location_name = LocationName{"UTC"};
clock_snapshot.location_name = location_name;
clock_snapshot.clock_auto_adjustment_enabled = 1;
clock_snapshot.type = initial_type;
clock_snapshot.ipc_u8 = unknown_u8;
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot));

View File

@@ -22,6 +22,7 @@ struct CalendarTime {
u8 hour;
u8 minute;
u8 second;
INSERT_PADDING_BYTES(1);
};
static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size");
@@ -29,7 +30,7 @@ struct CalendarAdditionalInfo {
u32_le day_of_week;
u32_le day_of_year;
std::array<u8, 8> name;
u8 is_dst;
INSERT_PADDING_BYTES(1);
s32_le utc_offset;
};
static_assert(sizeof(CalendarAdditionalInfo) == 0x18,
@@ -41,10 +42,8 @@ struct TimeZoneRule {
};
struct SteadyClockTimePoint {
using SourceID = std::array<u8, 16>;
u64_le value;
SourceID source_id;
INSERT_PADDING_WORDS(4);
};
static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size");
@@ -67,9 +66,8 @@ struct ClockSnapshot {
SteadyClockTimePoint steady_clock_timepoint;
LocationName location_name;
u8 clock_auto_adjustment_enabled;
u8 type;
u8 version;
INSERT_PADDING_BYTES(1);
u8 ipc_u8;
INSERT_PADDING_BYTES(2);
};
static_assert(sizeof(ClockSnapshot) == 0xd0, "ClockSnapshot is an invalid size");

View File

@@ -19,7 +19,6 @@
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/writable_event.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
@@ -503,12 +502,10 @@ private:
void TransactParcel(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 id = rp.Pop<u32>();
const auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
const u32 flags = rp.Pop<u32>();
LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
static_cast<u32>(transaction), flags);
u32 id = rp.Pop<u32>();
auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
u32 flags = rp.Pop<u32>();
LOG_DEBUG(Service_VI, "called, transaction={:X}", static_cast<u32>(transaction));
auto buffer_queue = nv_flinger->GetBufferQueue(id);
@@ -596,10 +593,9 @@ private:
void AdjustRefcount(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 id = rp.Pop<u32>();
const s32 addval = rp.PopRaw<s32>();
const u32 type = rp.Pop<u32>();
u32 id = rp.Pop<u32>();
s32 addval = rp.PopRaw<s32>();
u32 type = rp.Pop<u32>();
LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
type);
@@ -609,12 +605,11 @@ private:
void GetNativeHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 id = rp.Pop<u32>();
const u32 unknown = rp.Pop<u32>();
u32 id = rp.Pop<u32>();
u32 unknown = rp.Pop<u32>();
LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
const auto buffer_queue = nv_flinger->GetBufferQueue(id);
auto buffer_queue = nv_flinger->GetBufferQueue(id);
// TODO(Subv): Find out what this actually is.
IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -679,12 +674,11 @@ public:
private:
void SetLayerZ(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 layer_id = rp.Pop<u64>();
const u64 z_value = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called");
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id,
z_value);
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
u64 z_value = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -692,9 +686,8 @@ private:
void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 layer_id = rp.Pop<u64>();
const bool visibility = rp.Pop<bool>();
u64 layer_id = rp.Pop<u64>();
bool visibility = rp.Pop<bool>();
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:08X}, visibility={}", layer_id,
visibility);
@@ -803,27 +796,25 @@ public:
private:
void CloseDisplay(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 display = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called");
LOG_WARNING(Service_VI, "(STUBBED) called. display=0x{:016X}", display);
IPC::RequestParser rp{ctx};
u64 display = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const u32 unknown = rp.Pop<u32>();
u32 unknown = rp.Pop<u32>();
rp.Skip(1, false);
const u64 display = rp.Pop<u64>();
const u64 aruid = rp.Pop<u64>();
u64 display = rp.Pop<u64>();
u64 aruid = rp.Pop<u64>();
LOG_WARNING(Service_VI,
"(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
unknown, display, aruid);
const u64 layer_id = nv_flinger->CreateLayer(display);
u64 layer_id = nv_flinger->CreateLayer(display);
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
@@ -831,12 +822,11 @@ private:
}
void AddToLayerStack(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 stack = rp.Pop<u32>();
const u64 layer_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called");
LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack,
layer_id);
IPC::RequestParser rp{ctx};
u32 stack = rp.Pop<u32>();
u64 layer_id = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -844,9 +834,8 @@ private:
void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 layer_id = rp.Pop<u64>();
const bool visibility = rp.Pop<bool>();
u64 layer_id = rp.Pop<u64>();
bool visibility = rp.Pop<bool>();
LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id,
visibility);
@@ -899,23 +888,10 @@ private:
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const auto name_buf = rp.PopRaw<std::array<char, 0x40>>();
auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()});
}
void OpenDefaultDisplay(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_VI, "called");
OpenDisplayImpl(ctx, "Default");
}
void OpenDisplayImpl(Kernel::HLERequestContext& ctx, std::string_view name) {
const auto trim_pos = name.find('\0');
if (trim_pos != std::string_view::npos) {
name.remove_suffix(name.size() - trim_pos);
}
std::string name(name_buf.begin(), end);
ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
@@ -925,29 +901,20 @@ private:
}
void CloseDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const u64 display_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
// This literally does nothing internally in the actual service itself,
// and just returns a successful result code regardless of the input.
void SetDisplayEnabled(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_VI, "called.");
u64 display_id = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 display_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called");
LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(RESULT_SUCCESS);
@@ -966,12 +933,11 @@ private:
}
void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 scaling_mode = rp.Pop<u32>();
const u64 unknown = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called");
LOG_WARNING(Service_VI, "(STUBBED) called. scaling_mode=0x{:08X}, unknown=0x{:016X}",
scaling_mode, unknown);
IPC::RequestParser rp{ctx};
u32 scaling_mode = rp.Pop<u32>();
u64 unknown = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -991,19 +957,19 @@ private:
}
void OpenLayer(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_VI, "called");
IPC::RequestParser rp{ctx};
const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
const std::string display_name(name_buf.begin(), end);
std::string display_name(name_buf.begin(), end);
const u64 layer_id = rp.Pop<u64>();
const u64 aruid = rp.Pop<u64>();
u64 layer_id = rp.Pop<u64>();
u64 aruid = rp.Pop<u64>();
LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
const u64 display_id = nv_flinger->OpenDisplay(display_name);
const u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
u64 display_id = nv_flinger->OpenDisplay(display_name);
u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb{ctx, 4};
@@ -1012,17 +978,17 @@ private:
}
void CreateStrayLayer(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 flags = rp.Pop<u32>();
rp.Pop<u32>(); // padding
const u64 display_id = rp.Pop<u64>();
LOG_DEBUG(Service_VI, "called");
LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id);
IPC::RequestParser rp{ctx};
u32 flags = rp.Pop<u32>();
rp.Pop<u32>(); // padding
u64 display_id = rp.Pop<u64>();
// TODO(Subv): What's the difference between a Stray and a Managed layer?
const u64 layer_id = nv_flinger->CreateLayer(display_id);
const u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
u64 layer_id = nv_flinger->CreateLayer(display_id);
u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
NativeWindow native_window{buffer_queue_id};
IPC::ResponseBuilder rb{ctx, 6};
@@ -1032,22 +998,22 @@ private:
}
void DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 layer_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called");
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_VI, "(STUBBED) called");
IPC::RequestParser rp{ctx};
const u64 display_id = rp.Pop<u64>();
u64 display_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
const auto vsync_event = nv_flinger->GetVsyncEvent(display_id);
auto vsync_event = nv_flinger->GetVsyncEvent(display_id);
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
@@ -1116,9 +1082,9 @@ IApplicationDisplayService::IApplicationDisplayService(
"GetIndirectDisplayTransactionService"},
{1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
{1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
{1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"},
{1011, nullptr, "OpenDefaultDisplay"},
{1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
{1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
{1101, nullptr, "SetDisplayEnabled"},
{1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
{2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
{2021, nullptr, "CloseLayer"},

View File

@@ -3,6 +3,8 @@
// Refer to the license.txt file included.
#include "common/assert.h"
#include "core/core_timing.h"
#include "core/memory.h"
#include "video_core/engines/fermi_2d.h"
#include "video_core/engines/kepler_memory.h"
#include "video_core/engines/maxwell_3d.h"
@@ -124,9 +126,36 @@ u32 DepthFormatBytesPerPixel(DepthFormat format) {
}
}
// Note that, traditionally, methods are treated as 4-byte addressable locations, and hence
// their numbers are written down multiplied by 4 in Docs. Here we are not multiply by 4.
// So the values you see in docs might be multiplied by 4.
enum class BufferMethods {
BindObject = 0,
CountBufferMethods = 0x40,
BindObject = 0x0,
Nop = 0x2,
SemaphoreAddressHigh = 0x4,
SemaphoreAddressLow = 0x5,
SemaphoreSequence = 0x6,
SemaphoreTrigger = 0x7,
NotifyIntr = 0x8,
WrcacheFlush = 0x9,
Unk28 = 0xA,
Unk2c = 0xB,
RefCnt = 0x14,
SemaphoreAcquire = 0x1A,
SemaphoreRelease = 0x1B,
Unk70 = 0x1C,
Unk74 = 0x1D,
Unk78 = 0x1E,
Unk7c = 0x1F,
Yield = 0x20,
NonPullerMethods = 0x40,
};
enum class GpuSemaphoreOperation {
AcquireEqual = 0x1,
WriteLong = 0x2,
AcquireGequal = 0x4,
AcquireMask = 0x8,
};
void GPU::CallMethod(const MethodCall& method_call) {
@@ -135,20 +164,78 @@ void GPU::CallMethod(const MethodCall& method_call) {
ASSERT(method_call.subchannel < bound_engines.size());
if (method_call.method == static_cast<u32>(BufferMethods::BindObject)) {
// Bind the current subchannel to the desired engine id.
LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel,
method_call.argument);
bound_engines[method_call.subchannel] = static_cast<EngineID>(method_call.argument);
return;
if (ExecuteMethodOnEngine(method_call)) {
CallEngineMethod(method_call);
} else {
CallPullerMethod(method_call);
}
}
if (method_call.method < static_cast<u32>(BufferMethods::CountBufferMethods)) {
// TODO(Subv): Research and implement these methods.
LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented");
return;
bool GPU::ExecuteMethodOnEngine(const MethodCall& method_call) {
const auto method = static_cast<BufferMethods>(method_call.method);
return method >= BufferMethods::NonPullerMethods;
}
void GPU::CallPullerMethod(const MethodCall& method_call) {
regs.reg_array[method_call.method] = method_call.argument;
const auto method = static_cast<BufferMethods>(method_call.method);
switch (method) {
case BufferMethods::BindObject: {
ProcessBindMethod(method_call);
break;
}
case BufferMethods::Nop:
case BufferMethods::SemaphoreAddressHigh:
case BufferMethods::SemaphoreAddressLow:
case BufferMethods::SemaphoreSequence:
case BufferMethods::RefCnt:
break;
case BufferMethods::SemaphoreTrigger: {
ProcessSemaphoreTriggerMethod();
break;
}
case BufferMethods::NotifyIntr: {
// TODO(Kmather73): Research and implement this method.
LOG_ERROR(HW_GPU, "Special puller engine method NotifyIntr not implemented");
break;
}
case BufferMethods::WrcacheFlush: {
// TODO(Kmather73): Research and implement this method.
LOG_ERROR(HW_GPU, "Special puller engine method WrcacheFlush not implemented");
break;
}
case BufferMethods::Unk28: {
// TODO(Kmather73): Research and implement this method.
LOG_ERROR(HW_GPU, "Special puller engine method Unk28 not implemented");
break;
}
case BufferMethods::Unk2c: {
// TODO(Kmather73): Research and implement this method.
LOG_ERROR(HW_GPU, "Special puller engine method Unk2c not implemented");
break;
}
case BufferMethods::SemaphoreAcquire: {
ProcessSemaphoreAcquire();
break;
}
case BufferMethods::SemaphoreRelease: {
ProcessSemaphoreRelease();
break;
}
case BufferMethods::Yield: {
// TODO(Kmather73): Research and implement this method.
LOG_ERROR(HW_GPU, "Special puller engine method Yield not implemented");
break;
}
default:
LOG_ERROR(HW_GPU, "Special puller engine method {:X} not implemented",
static_cast<u32>(method));
break;
}
}
void GPU::CallEngineMethod(const MethodCall& method_call) {
const EngineID engine = bound_engines[method_call.subchannel];
switch (engine) {
@@ -172,4 +259,76 @@ void GPU::CallMethod(const MethodCall& method_call) {
}
}
void GPU::ProcessBindMethod(const MethodCall& method_call) {
// Bind the current subchannel to the desired engine id.
LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel,
method_call.argument);
bound_engines[method_call.subchannel] = static_cast<EngineID>(method_call.argument);
}
void GPU::ProcessSemaphoreTriggerMethod() {
const auto semaphoreOperationMask = 0xF;
const auto op =
static_cast<GpuSemaphoreOperation>(regs.semaphore_trigger & semaphoreOperationMask);
if (op == GpuSemaphoreOperation::WriteLong) {
auto address = memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
struct Block {
u32 sequence;
u32 zeros = 0;
u64 timestamp;
};
Block block{};
block.sequence = regs.semaphore_sequence;
// TODO(Kmather73): Generate a real GPU timestamp and write it here instead of
// CoreTiming
block.timestamp = CoreTiming::GetTicks();
Memory::WriteBlock(*address, &block, sizeof(block));
} else {
const auto address =
memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
const u32 word = Memory::Read32(*address);
if ((op == GpuSemaphoreOperation::AcquireEqual && word == regs.semaphore_sequence) ||
(op == GpuSemaphoreOperation::AcquireGequal &&
static_cast<s32>(word - regs.semaphore_sequence) > 0) ||
(op == GpuSemaphoreOperation::AcquireMask && (word & regs.semaphore_sequence))) {
// Nothing to do in this case
} else {
regs.acquire_source = true;
regs.acquire_value = regs.semaphore_sequence;
if (op == GpuSemaphoreOperation::AcquireEqual) {
regs.acquire_active = true;
regs.acquire_mode = false;
} else if (op == GpuSemaphoreOperation::AcquireGequal) {
regs.acquire_active = true;
regs.acquire_mode = true;
} else if (op == GpuSemaphoreOperation::AcquireMask) {
// TODO(kemathe) The acquire mask operation waits for a value that, ANDed with
// semaphore_sequence, gives a non-0 result
LOG_ERROR(HW_GPU, "Invalid semaphore operation AcquireMask not implemented");
} else {
LOG_ERROR(HW_GPU, "Invalid semaphore operation");
}
}
}
}
void GPU::ProcessSemaphoreRelease() {
const auto address = memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
Memory::Write32(*address, regs.semaphore_release);
}
void GPU::ProcessSemaphoreAcquire() {
const auto address = memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
const u32 word = Memory::Read32(*address);
const auto value = regs.semaphore_acquire;
if (word != value) {
regs.acquire_active = true;
regs.acquire_value = value;
// TODO(kemathe73) figure out how to do the acquire_timeout
regs.acquire_mode = false;
regs.acquire_source = false;
}
}
} // namespace Tegra

View File

@@ -156,6 +156,46 @@ public:
/// Returns a const reference to the GPU DMA pusher.
const Tegra::DmaPusher& DmaPusher() const;
struct Regs {
static constexpr size_t NUM_REGS = 0x100;
union {
struct {
INSERT_PADDING_WORDS(0x4);
struct {
u32 address_high;
u32 address_low;
GPUVAddr SmaphoreAddress() const {
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
address_low);
}
} smaphore_address;
u32 semaphore_sequence;
u32 semaphore_trigger;
INSERT_PADDING_WORDS(0xC);
// The puser and the puller share the reference counter, the pusher only has read
// access
u32 reference_count;
INSERT_PADDING_WORDS(0x5);
u32 semaphore_acquire;
u32 semaphore_release;
INSERT_PADDING_WORDS(0xE4);
// Puller state
u32 acquire_mode;
u32 acquire_source;
u32 acquire_active;
u32 acquire_timeout;
u32 acquire_value;
};
std::array<u32, NUM_REGS> reg_array;
};
} regs{};
private:
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
std::unique_ptr<Tegra::MemoryManager> memory_manager;
@@ -173,6 +213,37 @@ private:
std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
/// Inline memory engine
std::unique_ptr<Engines::KeplerMemory> kepler_memory;
void ProcessBindMethod(const MethodCall& method_call);
void ProcessSemaphoreTriggerMethod();
void ProcessSemaphoreRelease();
void ProcessSemaphoreAcquire();
// Calls a GPU puller method.
void CallPullerMethod(const MethodCall& method_call);
// Calls a GPU engine method.
void CallEngineMethod(const MethodCall& method_call);
// Determines where the method should be executed.
bool ExecuteMethodOnEngine(const MethodCall& method_call);
};
#define ASSERT_REG_POSITION(field_name, position) \
static_assert(offsetof(GPU::Regs, field_name) == position * 4, \
"Field " #field_name " has invalid position")
ASSERT_REG_POSITION(smaphore_address, 0x4);
ASSERT_REG_POSITION(semaphore_sequence, 0x6);
ASSERT_REG_POSITION(semaphore_trigger, 0x7);
ASSERT_REG_POSITION(reference_count, 0x14);
ASSERT_REG_POSITION(semaphore_acquire, 0x1A);
ASSERT_REG_POSITION(semaphore_release, 0x1B);
ASSERT_REG_POSITION(acquire_mode, 0x100);
ASSERT_REG_POSITION(acquire_source, 0x101);
ASSERT_REG_POSITION(acquire_active, 0x102);
ASSERT_REG_POSITION(acquire_timeout, 0x103);
ASSERT_REG_POSITION(acquire_value, 0x104);
#undef ASSERT_REG_POSITION
} // namespace Tegra

View File

@@ -1014,11 +1014,8 @@ u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader,
texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
Surface surface = res_cache.GetTextureSurface(texture, entry);
if (surface != nullptr) {
const GLuint handle =
entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle;
const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target();
state.texture_units[current_bindpoint].texture = handle;
state.texture_units[current_bindpoint].target = target;
state.texture_units[current_bindpoint].texture = surface->Texture().handle;
state.texture_units[current_bindpoint].target = surface->Target();
state.texture_units[current_bindpoint].swizzle.r =
MaxwellToGL::SwizzleSource(texture.tic.x_source);
state.texture_units[current_bindpoint].swizzle.g =

View File

@@ -44,17 +44,6 @@ struct FormatTuple {
bool compressed;
};
static void ApplyTextureDefaults(GLenum target, u32 max_mip_level) {
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, max_mip_level - 1);
if (max_mip_level == 1) {
glTexParameterf(target, GL_TEXTURE_LOD_BIAS, 1000.0);
}
}
void SurfaceParams::InitCacheParameters(Tegra::GPUVAddr gpu_addr_) {
auto& memory_manager{Core::System::GetInstance().GPU().MemoryManager()};
const auto cpu_addr{memory_manager.GpuToCpuAddress(gpu_addr_)};
@@ -541,9 +530,6 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
glActiveTexture(GL_TEXTURE0);
const auto& format_tuple = GetFormatTuple(params.pixel_format, params.component_type);
gl_internal_format = format_tuple.internal_format;
gl_is_compressed = format_tuple.compressed;
if (!format_tuple.compressed) {
// Only pre-create the texture for non-compressed textures.
switch (params.target) {
@@ -572,7 +558,15 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
}
}
ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(SurfaceTargetToGL(params.target), GL_TEXTURE_MAX_LEVEL,
params.max_mip_level - 1);
if (params.max_mip_level == 1) {
glTexParameterf(SurfaceTargetToGL(params.target), GL_TEXTURE_LOD_BIAS, 1000.0);
}
LabelGLObject(GL_TEXTURE, texture.handle, params.addr,
SurfaceParams::SurfaceTargetName(params.target));
@@ -870,31 +864,6 @@ void CachedSurface::UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle,
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
}
void CachedSurface::EnsureTextureView() {
if (texture_view.handle != 0)
return;
// Compressed texture are not being created with immutable storage
UNIMPLEMENTED_IF(gl_is_compressed);
const GLenum target{TargetLayer()};
texture_view.Create();
glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0,
params.max_mip_level, 0, 1);
OpenGLState cur_state = OpenGLState::GetCurState();
const auto& old_tex = cur_state.texture_units[0];
SCOPE_EXIT({
cur_state.texture_units[0] = old_tex;
cur_state.Apply();
});
cur_state.texture_units[0].texture = texture_view.handle;
cur_state.texture_units[0].target = target;
cur_state.Apply();
ApplyTextureDefaults(target, params.max_mip_level);
}
MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
if (params.type == SurfaceType::Fill)

View File

@@ -293,31 +293,10 @@ public:
return texture;
}
const OGLTexture& TextureLayer() {
if (params.is_layered) {
return Texture();
}
EnsureTextureView();
return texture_view;
}
GLenum Target() const {
return gl_target;
}
GLenum TargetLayer() const {
using VideoCore::Surface::SurfaceTarget;
switch (params.target) {
case SurfaceTarget::Texture1D:
return GL_TEXTURE_1D_ARRAY;
case SurfaceTarget::Texture2D:
return GL_TEXTURE_2D_ARRAY;
case SurfaceTarget::TextureCubemap:
return GL_TEXTURE_CUBE_MAP_ARRAY;
}
return Target();
}
const SurfaceParams& GetSurfaceParams() const {
return params;
}
@@ -332,16 +311,11 @@ public:
private:
void UploadGLMipmapTexture(u32 mip_map, GLuint read_fb_handle, GLuint draw_fb_handle);
void EnsureTextureView();
OGLTexture texture;
OGLTexture texture_view;
std::vector<std::vector<u8>> gl_buffer;
SurfaceParams params{};
GLenum gl_target{};
GLenum gl_internal_format{};
bool gl_is_compressed{};
std::size_t cached_size_in_bytes{};
SurfaceParams params;
GLenum gl_target;
std::size_t cached_size_in_bytes;
};
class RasterizerCacheOpenGL final : public RasterizerCache<Surface> {

View File

@@ -470,8 +470,6 @@ void Config::ReadValues() {
qt_config->value("enable_discord_presence", true).toBool();
UISettings::values.screenshot_resolution_factor =
static_cast<u16>(qt_config->value("screenshot_resolution_factor", 0).toUInt());
UISettings::values.select_user_on_boot =
qt_config->value("select_user_on_boot", false).toBool();
qt_config->beginGroup("UIGameList");
UISettings::values.show_unknown = qt_config->value("show_unknown", true).toBool();
@@ -682,7 +680,7 @@ void Config::SaveValues() {
qt_config->setValue("title_id", QVariant::fromValue<u64>(elem.first));
qt_config->beginWriteArray("disabled");
for (std::size_t j = 0; j < elem.second.size(); ++j) {
qt_config->setArrayIndex(static_cast<int>(j));
qt_config->setArrayIndex(j);
qt_config->setValue("d", QString::fromStdString(elem.second[j]));
}
qt_config->endArray();
@@ -695,7 +693,6 @@ void Config::SaveValues() {
qt_config->setValue("enable_discord_presence", UISettings::values.enable_discord_presence);
qt_config->setValue("screenshot_resolution_factor",
UISettings::values.screenshot_resolution_factor);
qt_config->setValue("select_user_on_boot", UISettings::values.select_user_on_boot);
qt_config->beginGroup("UIGameList");
qt_config->setValue("show_unknown", UISettings::values.show_unknown);

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>382</width>
<height>241</height>
<width>461</width>
<height>659</height>
</rect>
</property>
<property name="windowTitle">
@@ -15,71 +15,51 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="selectorList">
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>150</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="ConfigureGeneral" name="generalTab">
<attribute name="title">
<string>General</string>
</attribute>
</widget>
<widget class="ConfigureGameList" name="gameListTab">
<attribute name="title">
<string>Game List</string>
</attribute>
</widget>
<widget class="ConfigureSystem" name="systemTab">
<attribute name="title">
<string>System</string>
</attribute>
</widget>
<widget class="ConfigureInputSimple" name="inputTab">
<attribute name="title">
<string>Input</string>
</attribute>
</widget>
<widget class="ConfigureGraphics" name="graphicsTab">
<attribute name="title">
<string>Graphics</string>
</attribute>
</widget>
<widget class="ConfigureAudio" name="audioTab">
<attribute name="title">
<string>Audio</string>
</attribute>
</widget>
<widget class="ConfigureDebug" name="debugTab">
<attribute name="title">
<string>Debug</string>
</attribute>
</widget>
<widget class="ConfigureWeb" name="webTab">
<attribute name="title">
<string>Web</string>
</attribute>
</widget>
</widget>
</item>
</layout>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="ConfigureGeneral" name="generalTab">
<attribute name="title">
<string>General</string>
</attribute>
</widget>
<widget class="ConfigureGameList" name="gameListTab">
<attribute name="title">
<string>Game List</string>
</attribute>
</widget>
<widget class="ConfigureSystem" name="systemTab">
<attribute name="title">
<string>System</string>
</attribute>
</widget>
<widget class="ConfigureInputSimple" name="inputTab">
<attribute name="title">
<string>Input</string>
</attribute>
</widget>
<widget class="ConfigureGraphics" name="graphicsTab">
<attribute name="title">
<string>Graphics</string>
</attribute>
</widget>
<widget class="ConfigureAudio" name="audioTab">
<attribute name="title">
<string>Audio</string>
</attribute>
</widget>
<widget class="ConfigureDebug" name="debugTab">
<attribute name="title">
<string>Debug</string>
</attribute>
</widget>
<widget class="ConfigureWeb" name="webTab">
<attribute name="title">
<string>Web</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
@@ -97,6 +77,12 @@
<header>configuration/configure_general.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureGameList</class>
<extends>QWidget</extends>
<header>configuration/configure_gamelist.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureSystem</class>
<extends>QWidget</extends>
@@ -115,6 +101,12 @@
<header>configuration/configure_debug.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureInputSimple</class>
<extends>QWidget</extends>
<header>configuration/configure_input_simple.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureGraphics</class>
<extends>QWidget</extends>
@@ -127,18 +119,6 @@
<header>configuration/configure_web.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureGameList</class>
<extends>QWidget</extends>
<header>configuration/configure_gamelist.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>ConfigureInputSimple</class>
<extends>QWidget</extends>
<header>configuration/configure_input_simple.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>

View File

@@ -2,8 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QHash>
#include <QListWidgetItem>
#include "core/settings.h"
#include "ui_configure.h"
#include "yuzu/configuration/config.h"
@@ -15,13 +13,6 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, const HotkeyRegistry& registry
ui->setupUi(this);
ui->generalTab->PopulateHotkeyList(registry);
this->setConfiguration();
this->PopulateSelectionList();
connect(ui->selectorList, &QListWidget::itemSelectionChanged, this,
&ConfigureDialog::UpdateVisibleTabs);
adjustSize();
ui->selectorList->setCurrentRow(0);
}
ConfigureDialog::~ConfigureDialog() = default;
@@ -39,37 +30,3 @@ void ConfigureDialog::applyConfiguration() {
ui->webTab->applyConfiguration();
Settings::Apply();
}
void ConfigureDialog::PopulateSelectionList() {
const std::array<std::pair<QString, QStringList>, 4> items{
{{tr("General"), {tr("General"), tr("Web"), tr("Debug"), tr("Game List")}},
{tr("System"), {tr("System"), tr("Audio")}},
{tr("Graphics"), {tr("Graphics")}},
{tr("Controls"), {tr("Input")}}}};
for (const auto& entry : items) {
auto* const item = new QListWidgetItem(entry.first);
item->setData(Qt::UserRole, entry.second);
ui->selectorList->addItem(item);
}
}
void ConfigureDialog::UpdateVisibleTabs() {
const auto items = ui->selectorList->selectedItems();
if (items.isEmpty())
return;
const std::map<QString, QWidget*> widgets = {
{tr("General"), ui->generalTab}, {tr("System"), ui->systemTab},
{tr("Input"), ui->inputTab}, {tr("Graphics"), ui->graphicsTab},
{tr("Audio"), ui->audioTab}, {tr("Debug"), ui->debugTab},
{tr("Web"), ui->webTab}, {tr("Game List"), ui->gameListTab}};
ui->tabWidget->clear();
const QStringList tabs = items[0]->data(Qt::UserRole).toStringList();
for (const auto& tab : tabs)
ui->tabWidget->addTab(widgets.find(tab)->second, tab);
}

View File

@@ -24,8 +24,6 @@ public:
private:
void setConfiguration();
void UpdateVisibleTabs();
void PopulateSelectionList();
std::unique_ptr<Ui::ConfigureDialog> ui;
};

View File

@@ -30,7 +30,6 @@ ConfigureGeneral::~ConfigureGeneral() = default;
void ConfigureGeneral::setConfiguration() {
ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan);
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot);
ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit);
ui->enable_nfc->setChecked(Settings::values.enable_nfc);
@@ -43,7 +42,6 @@ void ConfigureGeneral::PopulateHotkeyList(const HotkeyRegistry& registry) {
void ConfigureGeneral::applyConfiguration() {
UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked();
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked();
UISettings::values.theme =
ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();

View File

@@ -38,13 +38,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toggle_user_on_boot">
<property name="text">
<string>Prompt for user on game boot</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@@ -120,7 +120,7 @@ void ConfigurePerGameGeneral::loadConfiguration() {
QPixmap map;
const auto bytes = control.second->ReadAllBytes();
map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
map.loadFromData(bytes.data(), bytes.size());
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
@@ -130,7 +130,7 @@ void ConfigurePerGameGeneral::loadConfiguration() {
scene->clear();
QPixmap map;
map.loadFromData(bytes.data(), static_cast<u32>(bytes.size()));
map.loadFromData(bytes.data(), bytes.size());
scene->addPixmap(map.scaled(ui->icon_view->width(), ui->icon_view->height(),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation));

View File

@@ -293,8 +293,8 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
QString processor;
switch (thread.GetProcessorID()) {
case Kernel::ThreadProcessorId::THREADPROCESSORID_IDEAL:
processor = tr("ideal");
case Kernel::ThreadProcessorId::THREADPROCESSORID_DEFAULT:
processor = tr("default");
break;
case Kernel::ThreadProcessorId::THREADPROCESSORID_0:
case Kernel::ThreadProcessorId::THREADPROCESSORID_1:

View File

@@ -687,26 +687,10 @@ bool GMainWindow::LoadROM(const QString& filename) {
return true;
}
void GMainWindow::SelectAndSetCurrentUser() {
QtProfileSelectionDialog dialog(this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
dialog.exec();
if (dialog.GetStatus()) {
Settings::values.current_user = static_cast<s32>(dialog.GetIndex());
}
}
void GMainWindow::BootGame(const QString& filename) {
LOG_INFO(Frontend, "yuzu starting...");
StoreRecentFile(filename); // Put the filename on top of the list
if (UISettings::values.select_user_on_boot) {
SelectAndSetCurrentUser();
}
if (!LoadROM(filename))
return;
@@ -843,25 +827,31 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
const std::string nand_dir = FileUtil::GetUserPath(FileUtil::UserPath::NANDDir);
ASSERT(program_id != 0);
const auto select_profile = [this]() -> s32 {
QtProfileSelectionDialog dialog(this);
dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint |
Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint);
dialog.setWindowModality(Qt::WindowModal);
dialog.exec();
Service::Account::ProfileManager manager{};
const auto user_ids = manager.GetAllUsers();
QStringList list;
for (const auto& user_id : user_ids) {
if (user_id == Service::Account::UUID{})
continue;
Service::Account::ProfileBase base;
if (!manager.GetProfileBase(user_id, base))
continue;
if (!dialog.GetStatus()) {
return -1;
}
list.push_back(QString::fromStdString(Common::StringFromFixedZeroTerminatedBuffer(
reinterpret_cast<const char*>(base.username.data()), base.username.size())));
}
return dialog.GetIndex();
};
const auto index = select_profile();
if (index == -1)
bool ok = false;
const auto index_string =
QInputDialog::getItem(this, tr("Select User"),
tr("Please select the user's save data you would like to open."),
list, Settings::values.current_user, false, &ok);
if (!ok)
return;
Service::Account::ProfileManager manager;
const auto index = list.indexOf(index_string);
ASSERT(index != -1 && index < 8);
const auto user_id = manager.GetUser(index);
ASSERT(user_id);
path = nand_dir + FileSys::SaveDataFactory::GetFullPath(FileSys::SaveDataSpaceId::NandUser,

View File

@@ -128,8 +128,6 @@ private:
void ShowTelemetryCallout();
void SetDiscordEnabled(bool state);
void SelectAndSetCurrentUser();
/**
* Stores the filename in the recently loaded files list.
* The new filename is stored at the beginning of the recently loaded files list.

View File

@@ -40,8 +40,6 @@ struct Values {
bool confirm_before_closing;
bool first_start;
bool select_user_on_boot;
// Discord RPC
bool enable_discord_presence;