diff options
Diffstat (limited to 'src/core')
28 files changed, 433 insertions, 183 deletions
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 1320bbe77..eda466a5d 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp @@ -10,6 +10,8 @@ namespace Core::Frontend { +GraphicsContext::~GraphicsContext() = default; + class EmuWindow::TouchState : public Input::Factory<Input::TouchDevice>, public std::enable_shared_from_this<TouchState> { public: diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 70a522556..e2c290dc1 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h @@ -19,6 +19,8 @@ namespace Core::Frontend { */ class GraphicsContext { public: + virtual ~GraphicsContext(); + /// Makes the graphics context current for the caller thread virtual void MakeCurrent() = 0; diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index ac0e1d796..5bb139483 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -438,7 +438,7 @@ inline float RequestParser::Pop() { template <> inline double RequestParser::Pop() { const u64 value = Pop<u64>(); - float real; + double real; std::memcpy(&real, &value, sizeof(real)); return real; } diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index fe710eb6e..42d9dd844 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -58,7 +58,7 @@ SharedPtr<WritableEvent> HLERequestContext::SleepClientThread( auto& kernel = Core::System::GetInstance().Kernel(); if (!writable_event) { // Create event if not provided - const auto pair = WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + const auto pair = WritableEvent::CreateEventPair(kernel, ResetType::Automatic, "HLE Pause Event: " + reason); writable_event = pair.writable; } diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 332876c27..2821176a7 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h @@ -33,8 +33,8 @@ enum class HandleType : u32 { }; enum class ResetType { - OneShot, ///< Reset automatically on object acquisition - Sticky, ///< Never reset automatically + Automatic, ///< Reset automatically on object acquisition + Manual, ///< Never reset automatically }; class Object : NonCopyable { diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp index c2b798a4e..06463cd26 100644 --- a/src/core/hle/kernel/readable_event.cpp +++ b/src/core/hle/kernel/readable_event.cpp @@ -21,8 +21,9 @@ bool ReadableEvent::ShouldWait(const Thread* thread) const { void ReadableEvent::Acquire(Thread* thread) { ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); - if (reset_type == ResetType::OneShot) + if (reset_type == ResetType::Automatic) { signaled = false; + } } void ReadableEvent::Signal() { diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 2dcf174c5..5a5851f66 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1255,8 +1255,8 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand return vm_manager.MapCodeMemory(dst_address, src_address, size); } -ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address, - u64 src_address, u64 size) { +static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_handle, + u64 dst_address, u64 src_address, u64 size) { LOG_DEBUG(Kernel_SVC, "called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, " "size=0x{:016X}", @@ -1342,7 +1342,7 @@ static void ExitProcess(Core::System& system) { /// Creates a new thread static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top, u32 priority, s32 processor_id) { - LOG_TRACE(Kernel_SVC, + LOG_DEBUG(Kernel_SVC, "called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, " "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}", entry_point, arg, stack_top, priority, processor_id, *out_handle); @@ -1402,7 +1402,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e /// Starts the thread for the provided handle static ResultCode StartThread(Core::System& system, Handle thread_handle) { - LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); + LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); @@ -1425,7 +1425,7 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { /// Called when a thread exits static void ExitThread(Core::System& system) { - LOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); + LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); auto* const current_thread = system.CurrentScheduler().GetCurrentThread(); current_thread->Stop(); @@ -1435,7 +1435,7 @@ static void ExitThread(Core::System& system) { /// Sleep the current thread static void SleepThread(Core::System& system, s64 nanoseconds) { - LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); + LOG_DEBUG(Kernel_SVC, "called nanoseconds={}", nanoseconds); enum class SleepType : s64 { YieldWithoutLoadBalancing = 0, @@ -1880,52 +1880,59 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, } static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, - u64 mask) { - LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:016X}, core=0x{:X}", thread_handle, - mask, core); + u64 affinity_mask) { + LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}", + thread_handle, core, affinity_mask); - const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); - const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); - if (!thread) { - LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", - thread_handle); - return ERR_INVALID_HANDLE; - } + const auto* const current_process = system.Kernel().CurrentProcess(); if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) { - const u8 ideal_cpu_core = thread->GetOwnerProcess()->GetIdealCore(); + const u8 ideal_cpu_core = current_process->GetIdealCore(); ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL)); // Set the target CPU to the ideal core specified by the process. core = ideal_cpu_core; - mask = 1ULL << core; - } - - if (mask == 0) { - LOG_ERROR(Kernel_SVC, "Mask is 0"); - return ERR_INVALID_COMBINATION; - } + affinity_mask = 1ULL << core; + } else { + const u64 core_mask = current_process->GetCoreMask(); + + if ((core_mask | affinity_mask) != core_mask) { + LOG_ERROR( + Kernel_SVC, + "Invalid processor ID specified (core_mask=0x{:08X}, affinity_mask=0x{:016X})", + core_mask, affinity_mask); + return ERR_INVALID_PROCESSOR_ID; + } - /// This value is used to only change the affinity mask without changing the current ideal core. - static constexpr u32 OnlyChangeMask = static_cast<u32>(-3); + if (affinity_mask == 0) { + LOG_ERROR(Kernel_SVC, "Specfified affinity mask is zero."); + return ERR_INVALID_COMBINATION; + } - if (core == OnlyChangeMask) { - core = thread->GetIdealCore(); - } else if (core >= Core::NUM_CPU_CORES && core != static_cast<u32>(-1)) { - LOG_ERROR(Kernel_SVC, "Invalid core specified, got {}", core); - return ERR_INVALID_PROCESSOR_ID; + if (core < Core::NUM_CPU_CORES) { + if ((affinity_mask & (1ULL << core)) == 0) { + LOG_ERROR(Kernel_SVC, + "Core is not enabled for the current mask, core={}, mask={:016X}", core, + affinity_mask); + return ERR_INVALID_COMBINATION; + } + } else if (core != static_cast<u32>(THREADPROCESSORID_DONT_CARE) && + core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) { + LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core); + return ERR_INVALID_PROCESSOR_ID; + } } - // Error out if the input core isn't enabled in the input mask. - if (core < Core::NUM_CPU_CORES && (mask & (1ull << core)) == 0) { - LOG_ERROR(Kernel_SVC, "Core is not enabled for the current mask, core={}, mask={:016X}", - core, mask); - return ERR_INVALID_COMBINATION; + const auto& handle_table = current_process->GetHandleTable(); + const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", + thread_handle); + return ERR_INVALID_HANDLE; } - thread->ChangeCore(core, mask); - + thread->ChangeCore(core, affinity_mask); return RESULT_SUCCESS; } @@ -1980,7 +1987,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle auto& kernel = system.Kernel(); const auto [readable_event, writable_event] = - WritableEvent::CreateEventPair(kernel, ResetType::Sticky, "CreateEvent"); + WritableEvent::CreateEventPair(kernel, ResetType::Manual, "CreateEvent"); HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable(); @@ -2183,8 +2190,8 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes, return RESULT_SUCCESS; } -ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids, - u32 out_thread_ids_size, Handle debug_handle) { +static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids, + u32 out_thread_ids_size, Handle debug_handle) { // TODO: Handle this case when debug events are supported. UNIMPLEMENTED_IF(debug_handle != InvalidHandle); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index f07332f02..b4b9cda7c 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -30,12 +30,21 @@ 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 + /// Indicates that no particular processor core is preferred. + THREADPROCESSORID_DONT_CARE = -1, + + /// Run thread on the ideal core specified by the process. + THREADPROCESSORID_IDEAL = -2, + + /// Indicates that the preferred processor ID shouldn't be updated in + /// a core mask setting operation. + THREADPROCESSORID_DONT_UPDATE = -3, + + 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) | diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 26a665bfd..1a32a109f 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -276,7 +276,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, + launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, "ISelfController:LaunchableEvent"); } @@ -442,10 +442,10 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c AppletMessageQueue::AppletMessageQueue() { auto& kernel = Core::System::GetInstance().Kernel(); - on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, + on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, "AMMessageQueue:OnMessageRecieved"); on_operation_mode_changed = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::OneShot, "AMMessageQueue:OperationModeChanged"); + kernel, Kernel::ResetType::Automatic, "AMMessageQueue:OperationModeChanged"); } AppletMessageQueue::~AppletMessageQueue() = default; @@ -835,6 +835,7 @@ void IStorageAccessor::Write(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_SIZE_OUT_OF_BOUNDS); + return; } std::memcpy(backing.buffer.data() + offset, data.data(), data.size()); @@ -857,6 +858,7 @@ void IStorageAccessor::Read(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_SIZE_OUT_OF_BOUNDS); + return; } ctx.WriteBuffer(backing.buffer.data() + offset, size); diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index 7f70b10df..e812c66e9 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -26,11 +26,11 @@ namespace Service::AM::Applets { AppletDataBroker::AppletDataBroker() { auto& kernel = Core::System::GetInstance().Kernel(); state_changed_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:StateChangedEvent"); + kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:StateChangedEvent"); pop_out_data_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:PopDataOutEvent"); + kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopDataOutEvent"); pop_interactive_out_data_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::Sticky, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); + kernel, Kernel::ResetType::Manual, "ILibraryAppletAccessor:PopInteractiveDataOutEvent"); } AppletDataBroker::~AppletDataBroker() = default; diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 51d8c26b4..bd4e38461 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp @@ -68,7 +68,7 @@ AOC_U::AOC_U() : ServiceFramework("aoc:u"), add_on_content(AccumulateAOCTitleIDs RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, + aoc_change_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, "GetAddOnContentListChanged:Event"); } diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index f43e512e9..6a01d4d29 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp @@ -50,7 +50,7 @@ void AudCtl::GetTargetVolumeMin(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Audio, "called."); // This service function is currently hardcoded on the - // actual console to this value (as of 6.0.0). + // actual console to this value (as of 8.0.0). constexpr s32 target_min_volume = 0; IPC::ResponseBuilder rb{ctx, 3}; @@ -62,7 +62,7 @@ void AudCtl::GetTargetVolumeMax(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Audio, "called."); // This service function is currently hardcoded on the - // actual console to this value (as of 6.0.0). + // actual console to this value (as of 8.0.0). constexpr s32 target_max_volume = 15; IPC::ResponseBuilder rb{ctx, 3}; diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 12875fb42..6ba41b20a 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -67,7 +67,7 @@ public: // This is the event handle used to check if the audio buffer was released auto& system = Core::System::GetInstance(); buffer_event = Kernel::WritableEvent::CreateEventPair( - system.Kernel(), Kernel::ResetType::Sticky, "IAudioOutBufferReleased"); + system.Kernel(), Kernel::ResetType::Manual, "IAudioOutBufferReleased"); stream = audio_core.OpenStream(system.CoreTiming(), audio_params.sample_rate, audio_params.channel_count, std::move(unique_name), diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 1dde6edb7..75db0c2dc 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -8,6 +8,7 @@ #include "audio_core/audio_renderer.h" #include "common/alignment.h" +#include "common/bit_util.h" #include "common/common_funcs.h" #include "common/logging/log.h" #include "common/string_util.h" @@ -46,7 +47,7 @@ public: auto& system = Core::System::GetInstance(); system_event = Kernel::WritableEvent::CreateEventPair( - system.Kernel(), Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent"); + system.Kernel(), Kernel::ResetType::Manual, "IAudioRenderer:SystemEvent"); renderer = std::make_unique<AudioCore::AudioRenderer>(system.CoreTiming(), audren_params, system_event.writable); } @@ -178,7 +179,7 @@ public: RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + buffer_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, "IAudioOutBufferReleasedEvent"); } @@ -262,64 +263,304 @@ void AudRenU::OpenAudioRenderer(Kernel::HLERequestContext& ctx) { OpenAudioRendererImpl(ctx); } +static u64 CalculateNumPerformanceEntries(const AudioCore::AudioRendererParameter& params) { + // +1 represents the final mix. + return u64{params.effect_count} + params.submix_count + params.sink_count + params.voice_count + + 1; +} + void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); LOG_DEBUG(Service_Audio, "called"); - u64 buffer_sz = Common::AlignUp(4 * params.mix_buffer_count, 0x40); - buffer_sz += params.submix_count * 1024; - buffer_sz += 0x940 * (params.submix_count + 1); - buffer_sz += 0x3F0 * params.voice_count; - buffer_sz += Common::AlignUp(8 * (params.submix_count + 1), 0x10); - buffer_sz += Common::AlignUp(8 * params.voice_count, 0x10); - buffer_sz += Common::AlignUp( - (0x3C0 * (params.sink_count + params.submix_count) + 4 * params.sample_count) * - (params.mix_buffer_count + 6), - 0x40); - - if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) { - const u32 count = params.submix_count + 1; - u64 node_count = Common::AlignUp(count, 0x40); - const 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; + // Several calculations below align the sizes being calculated + // onto a 64 byte boundary. + static constexpr u64 buffer_alignment_size = 64; + + // Some calculations that calculate portions of the buffer + // that will contain information, on the other hand, align + // the result of some of their calcularions on a 16 byte boundary. + static constexpr u64 info_field_alignment_size = 16; + + // Maximum detail entries that may exist at one time for performance + // frame statistics. + static constexpr u64 max_perf_detail_entries = 100; + + // Size of the data structure representing the bulk of the voice-related state. + static constexpr u64 voice_state_size = 0x100; + + // Size of the upsampler manager data structure + constexpr u64 upsampler_manager_size = 0x48; + + // Calculates the part of the size that relates to mix buffers. + const auto calculate_mix_buffer_sizes = [](const AudioCore::AudioRendererParameter& params) { + // As of 8.0.0 this is the maximum on voice channels. + constexpr u64 max_voice_channels = 6; + + // The service expects the sample_count member of the parameters to either be + // a value of 160 or 240, so the maximum sample count is assumed in order + // to adequately handle all values at runtime. + constexpr u64 default_max_sample_count = 240; + + const u64 total_mix_buffers = params.mix_buffer_count + max_voice_channels; + + u64 size = 0; + size += total_mix_buffers * (sizeof(s32) * params.sample_count); + size += total_mix_buffers * (sizeof(s32) * default_max_sample_count); + size += u64{params.submix_count} + params.sink_count; + size = Common::AlignUp(size, buffer_alignment_size); + size += Common::AlignUp(params.unknown_30, buffer_alignment_size); + size += Common::AlignUp(sizeof(s32) * params.mix_buffer_count, buffer_alignment_size); + return size; + }; + + // Calculates the portion of the size related to the mix data (and the sorting thereof). + const auto calculate_mix_info_size = [this](const AudioCore::AudioRendererParameter& params) { + // The size of the mixing info data structure. + constexpr u64 mix_info_size = 0x940; + + // Consists of total submixes with the final mix included. + const u64 total_mix_count = u64{params.submix_count} + 1; + + // The total number of effects that may be available to the audio renderer at any time. + constexpr u64 max_effects = 256; + + // Calculates the part of the size related to the audio node state. + // This will only be used if the audio revision supports the splitter. + const auto calculate_node_state_size = [](std::size_t num_nodes) { + // Internally within a nodestate, it appears to use a data structure + // similar to a std::bitset<64> twice. + constexpr u64 bit_size = Common::BitSize<u64>(); + constexpr u64 num_bitsets = 2; + + // Node state instances have three states internally for performing + // depth-first searches of nodes. Initialized, Found, and Done Sorting. + constexpr u64 num_states = 3; + + u64 size = 0; + size += (num_nodes * num_nodes) * sizeof(s32); + size += num_states * (num_nodes * sizeof(s32)); + size += num_bitsets * (Common::AlignUp(num_nodes, bit_size) / Common::BitSize<u8>()); + return size; + }; + + // Calculates the part of the size related to the adjacency (aka edge) matrix. + const auto calculate_edge_matrix_size = [](std::size_t num_nodes) { + return (num_nodes * num_nodes) * sizeof(s32); + }; + + u64 size = 0; + size += Common::AlignUp(sizeof(void*) * total_mix_count, info_field_alignment_size); + size += Common::AlignUp(mix_info_size * total_mix_count, info_field_alignment_size); + size += Common::AlignUp(sizeof(s32) * max_effects * params.submix_count, + info_field_alignment_size); + + if (IsFeatureSupported(AudioFeatures::Splitter, params.revision)) { + size += Common::AlignUp(calculate_node_state_size(total_mix_count) + + calculate_edge_matrix_size(total_mix_count), + info_field_alignment_size); } - 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.revision)) { - buffer_sz += 0xE0 * params.num_splitter_send_channels; - buffer_sz += 0x20 * params.splitter_count; - buffer_sz += Common::AlignUp(4 * params.num_splitter_send_channels, 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.performance_frame_count >= 1) { - output_sz = Common::AlignUp(((16 * params.sink_count + 16 * params.effect_count + - 16 * params.voice_count + 16) + - 0x658) * - (params.performance_frame_count + 1) + - 0xc0, - 0x40) + - output_sz; - } - output_sz = Common::AlignUp(output_sz + 0x1807e, 0x1000); + return size; + }; - IPC::ResponseBuilder rb{ctx, 4}; + // Calculates the part of the size related to voice channel info. + const auto calculate_voice_info_size = [](const AudioCore::AudioRendererParameter& params) { + constexpr u64 voice_info_size = 0x220; + constexpr u64 voice_resource_size = 0xD0; + + u64 size = 0; + size += Common::AlignUp(sizeof(void*) * params.voice_count, info_field_alignment_size); + size += Common::AlignUp(voice_info_size * params.voice_count, info_field_alignment_size); + size += + Common::AlignUp(voice_resource_size * params.voice_count, info_field_alignment_size); + size += Common::AlignUp(voice_state_size * params.voice_count, info_field_alignment_size); + return size; + }; + + // Calculates the part of the size related to memory pools. + const auto calculate_memory_pools_size = [](const AudioCore::AudioRendererParameter& params) { + const u64 num_memory_pools = sizeof(s32) * (u64{params.effect_count} + params.voice_count); + const u64 memory_pool_info_size = 0x20; + return Common::AlignUp(num_memory_pools * memory_pool_info_size, info_field_alignment_size); + }; + + // Calculates the part of the size related to the splitter context. + const auto calculate_splitter_context_size = + [this](const AudioCore::AudioRendererParameter& params) -> u64 { + if (!IsFeatureSupported(AudioFeatures::Splitter, params.revision)) { + return 0; + } + + constexpr u64 splitter_info_size = 0x20; + constexpr u64 splitter_destination_data_size = 0xE0; + + u64 size = 0; + size += params.num_splitter_send_channels; + size += + Common::AlignUp(splitter_info_size * params.splitter_count, info_field_alignment_size); + size += Common::AlignUp(splitter_destination_data_size * params.num_splitter_send_channels, + info_field_alignment_size); + + return size; + }; + + // Calculates the part of the size related to the upsampler info. + const auto calculate_upsampler_info_size = [](const AudioCore::AudioRendererParameter& params) { + constexpr u64 upsampler_info_size = 0x280; + // Yes, using the buffer size over info alignment size is intentional here. + return Common::AlignUp(upsampler_info_size * (u64{params.submix_count} + params.sink_count), + buffer_alignment_size); + }; + + // Calculates the part of the size related to effect info. + const auto calculate_effect_info_size = [](const AudioCore::AudioRendererParameter& params) { + constexpr u64 effect_info_size = 0x2B0; + return Common::AlignUp(effect_info_size * params.effect_count, info_field_alignment_size); + }; + + // Calculates the part of the size related to audio sink info. + const auto calculate_sink_info_size = [](const AudioCore::AudioRendererParameter& params) { + const u64 sink_info_size = 0x170; + return Common::AlignUp(sink_info_size * params.sink_count, info_field_alignment_size); + }; + + // Calculates the part of the size related to voice state info. + const auto calculate_voice_state_size = [](const AudioCore::AudioRendererParameter& params) { + const u64 voice_state_size = 0x100; + const u64 additional_size = buffer_alignment_size - 1; + return Common::AlignUp(voice_state_size * params.voice_count + additional_size, + info_field_alignment_size); + }; + + // Calculates the part of the size related to performance statistics. + const auto calculate_perf_size = [this](const AudioCore::AudioRendererParameter& params) { + // Extra size value appended to the end of the calculation. + constexpr u64 appended = 128; + + // Whether or not we assume the newer version of performance metrics data structures. + const bool is_v2 = + IsFeatureSupported(AudioFeatures::PerformanceMetricsVersion2, params.revision); + + // Data structure sizes + constexpr u64 perf_statistics_size = 0x0C; + const u64 header_size = is_v2 ? 0x30 : 0x18; + const u64 entry_size = is_v2 ? 0x18 : 0x10; + const u64 detail_size = is_v2 ? 0x18 : 0x10; + + const u64 entry_count = CalculateNumPerformanceEntries(params); + const u64 size_per_frame = + header_size + (entry_size * entry_count) + (detail_size * max_perf_detail_entries); + + u64 size = 0; + size += Common::AlignUp(size_per_frame * params.performance_frame_count + 1, + buffer_alignment_size); + size += Common::AlignUp(perf_statistics_size, buffer_alignment_size); + size += appended; + return size; + }; + + // Calculates the part of the size that relates to the audio command buffer. + const auto calculate_command_buffer_size = + [this](const AudioCore::AudioRendererParameter& params) { + constexpr u64 alignment = (buffer_alignment_size - 1) * 2; + + if (!IsFeatureSupported(AudioFeatures::VariadicCommandBuffer, params.revision)) { + constexpr u64 command_buffer_size = 0x18000; + + return command_buffer_size + alignment; + } + + // When the variadic command buffer is supported, this means + // the command generator for the audio renderer can issue commands + // that are (as one would expect), variable in size. So what we need to do + // is determine the maximum possible size for a few command data structures + // then multiply them by the amount of present commands indicated by the given + // respective audio parameters. + + constexpr u64 max_biquad_filters = 2; + constexpr u64 max_mix_buffers = 24; + + constexpr u64 biquad_filter_command_size = 0x2C; + + constexpr u64 depop_mix_command_size = 0x24; + constexpr u64 depop_setup_command_size = 0x50; + + constexpr u64 effect_command_max_size = 0x540; + + constexpr u64 mix_command_size = 0x1C; + constexpr u64 mix_ramp_command_size = 0x24; + constexpr u64 mix_ramp_grouped_command_size = 0x13C; + + constexpr u64 perf_command_size = 0x28; + + constexpr u64 sink_command_size = 0x130; + + constexpr u64 submix_command_max_size = + depop_mix_command_size + (mix_command_size * max_mix_buffers) * max_mix_buffers; + + constexpr u64 volume_command_size = 0x1C; + constexpr u64 volume_ramp_command_size = 0x20; + + constexpr u64 voice_biquad_filter_command_size = + biquad_filter_command_size * max_biquad_filters; + constexpr u64 voice_data_command_size = 0x9C; + const u64 voice_command_max_size = + (params.splitter_count * depop_setup_command_size) + + (voice_data_command_size + voice_biquad_filter_command_size + + volume_ramp_command_size + mix_ramp_grouped_command_size); + + // Now calculate the individual elements that comprise the size and add them together. + const u64 effect_commands_size = params.effect_count * effect_command_max_size; + + const u64 final_mix_commands_size = + depop_mix_command_size + volume_command_size * max_mix_buffers; + const u64 perf_commands_size = + perf_command_size * + (CalculateNumPerformanceEntries(params) + max_perf_detail_entries); + + const u64 sink_commands_size = params.sink_count * sink_command_size; + + const u64 splitter_commands_size = + params.num_splitter_send_channels * max_mix_buffers * mix_ramp_command_size; + + const u64 submix_commands_size = params.submix_count * submix_command_max_size; + + const u64 voice_commands_size = params.voice_count * voice_command_max_size; + + return effect_commands_size + final_mix_commands_size + perf_commands_size + + sink_commands_size + splitter_commands_size + submix_commands_size + + voice_commands_size + alignment; + }; + + IPC::RequestParser rp{ctx}; + const auto params = rp.PopRaw<AudioCore::AudioRendererParameter>(); + + u64 size = 0; + size += calculate_mix_buffer_sizes(params); + size += calculate_mix_info_size(params); + size += calculate_voice_info_size(params); + size += upsampler_manager_size; + size += calculate_memory_pools_size(params); + size += calculate_splitter_context_size(params); + + size = Common::AlignUp(size, buffer_alignment_size); + + size += calculate_upsampler_info_size(params); + size += calculate_effect_info_size(params); + size += calculate_sink_info_size(params); + size += calculate_voice_state_size(params); + size += calculate_perf_size(params); + size += calculate_command_buffer_size(params); + + // finally, 4KB page align the size, and we're done. + size = Common::AlignUp(size, 4096); + + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push<u64>(output_sz); + rb.Push<u64>(size); - LOG_DEBUG(Service_Audio, "buffer_size=0x{:X}", output_sz); + LOG_DEBUG(Service_Audio, "buffer_size=0x{:X}", size); } void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) { @@ -357,10 +598,15 @@ void AudRenU::OpenAudioRendererImpl(Kernel::HLERequestContext& ctx) { } bool AudRenU::IsFeatureSupported(AudioFeatures feature, u32_le revision) const { - u32_be version_num = (revision - Common::MakeMagic('R', 'E', 'V', '0')); // Byte swap + // Byte swap + const u32_be version_num = revision - Common::MakeMagic('R', 'E', 'V', '0'); + switch (feature) { case AudioFeatures::Splitter: - return version_num >= 2u; + return version_num >= 2U; + case AudioFeatures::PerformanceMetricsVersion2: + case AudioFeatures::VariadicCommandBuffer: + return version_num >= 5U; default: return false; } diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h index e55d25973..1d3c8df61 100644 --- a/src/core/hle/service/audio/audren_u.h +++ b/src/core/hle/service/audio/audren_u.h @@ -28,6 +28,8 @@ private: enum class AudioFeatures : u32 { Splitter, + PerformanceMetricsVersion2, + VariadicCommandBuffer, }; bool IsFeatureSupported(AudioFeatures feature, u32_le revision) const; diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index 974ff8e1a..3c7ca2c44 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp @@ -34,8 +34,8 @@ public: RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - register_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, - "BT:RegisterEvent"); + register_event = Kernel::WritableEvent::CreateEventPair( + kernel, Kernel::ResetType::Automatic, "BT:RegisterEvent"); } private: diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 4f15c3f19..b439ee7ec 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp @@ -57,13 +57,13 @@ public: RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + scan_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, "IBtmUserCore:ScanEvent"); connection_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::OneShot, "IBtmUserCore:ConnectionEvent"); + kernel, Kernel::ResetType::Automatic, "IBtmUserCore:ConnectionEvent"); service_discovery = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::OneShot, "IBtmUserCore:Discovery"); - config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + kernel, Kernel::ResetType::Automatic, "IBtmUserCore:Discovery"); + config_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, "IBtmUserCore:ConfigEvent"); } diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index e7fc7a619..fdd6d79a2 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -170,7 +170,7 @@ void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) { void Controller_NPad::OnInit() { auto& kernel = Core::System::GetInstance().Kernel(); styleset_changed_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged"); + kernel, Kernel::ResetType::Automatic, "npad:NpadStyleSetChanged"); if (!IsControllerActivated()) { return; diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index c6babdd4d..a5cb06f8a 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -26,7 +26,7 @@ constexpr ResultCode ERR_NO_APPLICATION_AREA(ErrorModule::NFP, 152); Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) : ServiceFramework(name), module(std::move(module)) { auto& kernel = Core::System::GetInstance().Kernel(); - nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + nfc_tag_load = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, "IUser:NFCTagDetected"); } @@ -67,9 +67,9 @@ public: auto& kernel = Core::System::GetInstance().Kernel(); deactivate_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); + kernel, Kernel::ResetType::Automatic, "IUser:DeactivateEvent"); availability_change_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent"); + kernel, Kernel::ResetType::Automatic, "IUser:AvailabilityChangeEvent"); } private: diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index f92571008..76b12b482 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -62,9 +62,9 @@ public: RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + event1 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, "IRequest:Event1"); - event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + event2 = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, "IRequest:Event2"); } diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index 0dabcd23b..f319a3ca1 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -141,7 +141,7 @@ public: auto& kernel = Core::System::GetInstance().Kernel(); finished_event = Kernel::WritableEvent::CreateEventPair( - kernel, Kernel::ResetType::OneShot, + kernel, Kernel::ResetType::Automatic, "IEnsureNetworkClockAvailabilityService:FinishEvent"); } diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 3b9ab4b14..b60fc748b 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -129,7 +129,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) RegisterHandlers(functions); auto& kernel = Core::System::GetInstance().Kernel(); - query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::OneShot, + query_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Automatic, "NVDRV::query_event"); } diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 4d150fc71..5731e815f 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -16,7 +16,7 @@ namespace Service::NVFlinger { BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { auto& kernel = Core::System::GetInstance().Kernel(); - buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Sticky, + buffer_wait_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, "BufferQueue NativeHandle"); } diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 4ecb6bcef..298d85011 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp @@ -2,16 +2,15 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> #include <chrono> #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/client_port.h" -#include "core/hle/kernel/client_session.h" #include "core/hle/service/set/set.h" #include "core/settings.h" namespace Service::Set { - +namespace { constexpr std::array<LanguageCode, 17> available_language_codes = {{ LanguageCode::JA, LanguageCode::EN_US, @@ -32,41 +31,35 @@ constexpr std::array<LanguageCode, 17> available_language_codes = {{ LanguageCode::ZH_HANT, }}; -constexpr std::size_t pre4_0_0_max_entries = 0xF; -constexpr std::size_t post4_0_0_max_entries = 0x40; +constexpr std::size_t pre4_0_0_max_entries = 15; +constexpr std::size_t post4_0_0_max_entries = 17; constexpr ResultCode ERR_INVALID_LANGUAGE{ErrorModule::Settings, 625}; -LanguageCode GetLanguageCodeFromIndex(std::size_t index) { - return available_language_codes.at(index); +void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t num_language_codes) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast<u32>(num_language_codes)); } -template <std::size_t size> -static std::array<LanguageCode, size> MakeLanguageCodeSubset() { - std::array<LanguageCode, size> arr; - std::copy_n(available_language_codes.begin(), size, arr.begin()); - return arr; +void GetAvailableLanguageCodesImpl(Kernel::HLERequestContext& ctx, std::size_t max_size) { + const std::size_t requested_amount = ctx.GetWriteBufferSize() / sizeof(LanguageCode); + const std::size_t copy_amount = std::min(requested_amount, max_size); + const std::size_t copy_size = copy_amount * sizeof(LanguageCode); + + ctx.WriteBuffer(available_language_codes.data(), copy_size); + PushResponseLanguageCode(ctx, copy_amount); } +} // Anonymous namespace -static void PushResponseLanguageCode(Kernel::HLERequestContext& ctx, std::size_t max_size) { - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(RESULT_SUCCESS); - if (available_language_codes.size() > max_size) { - rb.Push(static_cast<u32>(max_size)); - } else { - rb.Push(static_cast<u32>(available_language_codes.size())); - } +LanguageCode GetLanguageCodeFromIndex(std::size_t index) { + return available_language_codes.at(index); } void SET::GetAvailableLanguageCodes(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); - if (available_language_codes.size() > pre4_0_0_max_entries) { - ctx.WriteBuffer(MakeLanguageCodeSubset<pre4_0_0_max_entries>()); - } else { - ctx.WriteBuffer(available_language_codes); - } - PushResponseLanguageCode(ctx, pre4_0_0_max_entries); + GetAvailableLanguageCodesImpl(ctx, pre4_0_0_max_entries); } void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { @@ -87,12 +80,7 @@ void SET::MakeLanguageCode(Kernel::HLERequestContext& ctx) { void SET::GetAvailableLanguageCodes2(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); - if (available_language_codes.size() > post4_0_0_max_entries) { - ctx.WriteBuffer(MakeLanguageCodeSubset<post4_0_0_max_entries>()); - } else { - ctx.WriteBuffer(available_language_codes); - } - PushResponseLanguageCode(ctx, post4_0_0_max_entries); + GetAvailableLanguageCodesImpl(ctx, post4_0_0_max_entries); } void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { @@ -102,9 +90,9 @@ void SET::GetAvailableLanguageCodeCount(Kernel::HLERequestContext& ctx) { } void SET::GetAvailableLanguageCodeCount2(Kernel::HLERequestContext& ctx) { - PushResponseLanguageCode(ctx, post4_0_0_max_entries); - LOG_DEBUG(Service_SET, "called"); + + PushResponseLanguageCode(ctx, post4_0_0_max_entries); } void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index 01d80311b..a8d088305 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -17,7 +17,7 @@ namespace Service::VI { 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::Manual, fmt::format("Display VSync Event {}", id)); } diff --git a/src/core/memory.h b/src/core/memory.h index b9fa18b1d..04e2c5f1d 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -72,15 +72,6 @@ u8* GetPointer(VAddr vaddr); std::string ReadCString(VAddr vaddr, std::size_t max_length); -enum class FlushMode { - /// Write back modified surfaces to RAM - Flush, - /// Remove region from the cache - Invalidate, - /// Write back modified surfaces to RAM, and also remove them from the cache - FlushAndInvalidate, -}; - /** * Mark each page touching the region as cached. */ diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index e1db06811..4b17bada5 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -102,12 +102,6 @@ bool VerifyLogin(const std::string& username, const std::string& token) { } TelemetrySession::TelemetrySession() { -#ifdef ENABLE_WEB_SERVICE - backend = std::make_unique<WebService::TelemetryJson>( - Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); -#else - backend = std::make_unique<Telemetry::NullVisitor>(); -#endif // Log one-time top-level information AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); @@ -175,9 +169,14 @@ TelemetrySession::~TelemetrySession() { .count()}; AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time); +#ifdef ENABLE_WEB_SERVICE + auto backend = std::make_unique<WebService::TelemetryJson>( + Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); +#else + auto backend = std::make_unique<Telemetry::NullVisitor>(); +#endif + // Complete the session, submitting to web service if necessary - // This is just a placeholder to wrap up the session once the core completes and this is - // destroyed. This will be moved elsewhere once we are actually doing real I/O with the service. field_collection.Accept(*backend); if (Settings::values.enable_telemetry) backend->Complete(); @@ -186,6 +185,8 @@ TelemetrySession::~TelemetrySession() { bool TelemetrySession::SubmitTestcase() { #ifdef ENABLE_WEB_SERVICE + auto backend = std::make_unique<WebService::TelemetryJson>( + Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); field_collection.Accept(*backend); return backend->SubmitTestcase(); #else diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index 023612b79..cae5a45a0 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h @@ -39,7 +39,6 @@ public: private: Telemetry::FieldCollection field_collection; ///< Tracks all added fields for the session - std::unique_ptr<Telemetry::VisitorInterface> backend; ///< Backend interface that logs fields }; /** |