From 765c7bb93a5d63d9ea54d1679f2d1b0c000d26f0 Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Mon, 12 Feb 2024 05:52:53 +0100 Subject: [PATCH] early-access version 4134 --- README.md | 2 +- .../bcat/news/newly_arrived_event_holder.cpp | 2 +- .../bcat/news/news_database_service.cpp | 24 ++- .../service/bcat/news/news_database_service.h | 8 + .../hle/service/bcat/news/news_service.cpp | 17 +- src/core/hle/service/bcat/news/news_service.h | 4 + .../bcat/news/overwrite_event_holder.cpp | 2 +- .../hle/service/bcat/news/service_creator.cpp | 10 +- src/video_core/control/scheduler.cpp | 155 +++++++++++------- src/video_core/control/scheduler.h | 1 + src/video_core/texture_cache/image_info.cpp | 1 + src/video_core/texture_cache/image_info.h | 1 + src/video_core/texture_cache/texture_cache.h | 15 +- src/yuzu/hotkeys.cpp | 6 +- 14 files changed, 166 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 5bb2c9dd8..10fd85b8d 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 4132. +This is the source code for early-access 4134. ## Legal Notice diff --git a/src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp b/src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp index 5be167fce..ed393f7a2 100755 --- a/src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp +++ b/src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp @@ -12,7 +12,7 @@ INewlyArrivedEventHolder::INewlyArrivedEventHolder(Core::System& system_) "INewlyArrivedEventHolder"} { // clang-format off static const FunctionInfo functions[] = { - {0, C<&INewlyArrivedEventHolder::Get>, "Get"}, + {0, D<&INewlyArrivedEventHolder::Get>, "Get"}, }; // clang-format on diff --git a/src/core/hle/service/bcat/news/news_database_service.cpp b/src/core/hle/service/bcat/news/news_database_service.cpp index 18109f9b0..b94ef0636 100755 --- a/src/core/hle/service/bcat/news/news_database_service.cpp +++ b/src/core/hle/service/bcat/news/news_database_service.cpp @@ -11,12 +11,12 @@ INewsDatabaseService::INewsDatabaseService(Core::System& system_) // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetListV1"}, - {1, C<&INewsDatabaseService::Count>, "Count"}, + {1, D<&INewsDatabaseService::Count>, "Count"}, {2, nullptr, "CountWithKey"}, {3, nullptr, "UpdateIntegerValue"}, - {4, nullptr, "UpdateIntegerValueWithAddition"}, + {4, D<&INewsDatabaseService::UpdateIntegerValueWithAddition>, "UpdateIntegerValueWithAddition"}, {5, nullptr, "UpdateStringValue"}, - {1000, nullptr, "GetList"}, + {1000, D<&INewsDatabaseService::GetList>, "GetList"}, }; // clang-format on @@ -32,4 +32,22 @@ Result INewsDatabaseService::Count(Out out_count, R_SUCCEED(); } +Result INewsDatabaseService::UpdateIntegerValueWithAddition( + u32 value, InBuffer buffer_data_1, + InBuffer buffer_data_2) { + LOG_WARNING(Service_BCAT, "(STUBBED) called, value={}, buffer_size_1={}, buffer_data_2={}", + value, buffer_data_1.size(), buffer_data_2.size()); + R_SUCCEED(); +} + +Result INewsDatabaseService::GetList(Out out_count, u32 value, + OutBuffer out_buffer_data, + InBuffer buffer_data_1, + InBuffer buffer_data_2) { + LOG_WARNING(Service_BCAT, "(STUBBED) called, value={}, buffer_size_1={}, buffer_data_2={}", + value, buffer_data_1.size(), buffer_data_2.size()); + *out_count = 0; + R_SUCCEED(); +} + } // namespace Service::News diff --git a/src/core/hle/service/bcat/news/news_database_service.h b/src/core/hle/service/bcat/news/news_database_service.h index f5916634b..860b7074c 100755 --- a/src/core/hle/service/bcat/news/news_database_service.h +++ b/src/core/hle/service/bcat/news/news_database_service.h @@ -19,6 +19,14 @@ public: private: Result Count(Out out_count, InBuffer buffer_data); + + Result UpdateIntegerValueWithAddition(u32 value, InBuffer buffer_data_1, + InBuffer buffer_data_2); + + Result GetList(Out out_count, u32 value, + OutBuffer out_buffer_data, + InBuffer buffer_data_1, + InBuffer buffer_data_2); }; } // namespace Service::News diff --git a/src/core/hle/service/bcat/news/news_service.cpp b/src/core/hle/service/bcat/news/news_service.cpp index e19cea7b5..bc6c2afd2 100755 --- a/src/core/hle/service/bcat/news/news_service.cpp +++ b/src/core/hle/service/bcat/news/news_service.cpp @@ -11,10 +11,10 @@ INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "I static const FunctionInfo functions[] = { {10100, nullptr, "PostLocalNews"}, {20100, nullptr, "SetPassphrase"}, - {30100, C<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"}, + {30100, D<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"}, {30101, nullptr, "GetTopicList"}, {30110, nullptr, "Unknown30110"}, - {30200, nullptr, "IsSystemUpdateRequired"}, + {30200, D<&INewsService::IsSystemUpdateRequired>, "IsSystemUpdateRequired"}, {30201, nullptr, "Unknown30201"}, {30210, nullptr, "Unknown30210"}, {30300, nullptr, "RequestImmediateReception"}, @@ -24,7 +24,7 @@ INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "I {30901, nullptr, "Unknown30901"}, {30902, nullptr, "Unknown30902"}, {40100, nullptr, "SetSubscriptionStatus"}, - {40101, nullptr, "RequestAutoSubscription"}, + {40101, D<&INewsService::RequestAutoSubscription>, "RequestAutoSubscription"}, {40200, nullptr, "ClearStorage"}, {40201, nullptr, "ClearSubscriptionStatusAll"}, {90100, nullptr, "GetNewsDatabaseDump"}, @@ -43,4 +43,15 @@ Result INewsService::GetSubscriptionStatus(Out out_status, R_SUCCEED(); } +Result INewsService::IsSystemUpdateRequired(Out out_is_system_update_required) { + LOG_WARNING(Service_BCAT, "(STUBBED) called"); + *out_is_system_update_required = false; + R_SUCCEED(); +} + +Result INewsService::RequestAutoSubscription(u64 value) { + LOG_WARNING(Service_BCAT, "(STUBBED) called"); + R_SUCCEED(); +} + } // namespace Service::News diff --git a/src/core/hle/service/bcat/news/news_service.h b/src/core/hle/service/bcat/news/news_service.h index 8d06be9d6..f1716a302 100755 --- a/src/core/hle/service/bcat/news/news_service.h +++ b/src/core/hle/service/bcat/news/news_service.h @@ -19,6 +19,10 @@ public: private: Result GetSubscriptionStatus(Out out_status, InBuffer buffer_data); + + Result IsSystemUpdateRequired(Out out_is_system_update_required); + + Result RequestAutoSubscription(u64 value); }; } // namespace Service::News diff --git a/src/core/hle/service/bcat/news/overwrite_event_holder.cpp b/src/core/hle/service/bcat/news/overwrite_event_holder.cpp index c32a5ca8f..1712971e4 100755 --- a/src/core/hle/service/bcat/news/overwrite_event_holder.cpp +++ b/src/core/hle/service/bcat/news/overwrite_event_holder.cpp @@ -11,7 +11,7 @@ IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_) "IOverwriteEventHolder"} { // clang-format off static const FunctionInfo functions[] = { - {0, C<&IOverwriteEventHolder::Get>, "Get"}, + {0, D<&IOverwriteEventHolder::Get>, "Get"}, }; // clang-format on diff --git a/src/core/hle/service/bcat/news/service_creator.cpp b/src/core/hle/service/bcat/news/service_creator.cpp index d5ba5dff7..a1b22c004 100755 --- a/src/core/hle/service/bcat/news/service_creator.cpp +++ b/src/core/hle/service/bcat/news/service_creator.cpp @@ -15,11 +15,11 @@ IServiceCreator::IServiceCreator(Core::System& system_, u32 permissions_, const : ServiceFramework{system_, name_}, permissions{permissions_} { // clang-format off static const FunctionInfo functions[] = { - {0, C<&IServiceCreator::CreateNewsService>, "CreateNewsService"}, - {1, C<&IServiceCreator::CreateNewlyArrivedEventHolder>, "CreateNewlyArrivedEventHolder"}, - {2, C<&IServiceCreator::CreateNewsDataService>, "CreateNewsDataService"}, - {3, C<&IServiceCreator::CreateNewsDatabaseService>, "CreateNewsDatabaseService"}, - {4, C<&IServiceCreator::CreateOverwriteEventHolder>, "CreateOverwriteEventHolder"}, + {0, D<&IServiceCreator::CreateNewsService>, "CreateNewsService"}, + {1, D<&IServiceCreator::CreateNewlyArrivedEventHolder>, "CreateNewlyArrivedEventHolder"}, + {2, D<&IServiceCreator::CreateNewsDataService>, "CreateNewsDataService"}, + {3, D<&IServiceCreator::CreateNewsDatabaseService>, "CreateNewsDatabaseService"}, + {4, D<&IServiceCreator::CreateOverwriteEventHolder>, "CreateOverwriteEventHolder"}, }; // clang-format on diff --git a/src/video_core/control/scheduler.cpp b/src/video_core/control/scheduler.cpp index 91d81500a..f57efd189 100755 --- a/src/video_core/control/scheduler.cpp +++ b/src/video_core/control/scheduler.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "common/assert.h" #include "common/fiber.h" @@ -53,29 +54,30 @@ void Scheduler::Init() { } void Scheduler::Resume() { - bool pending_work; - do { - pending_work = false; - { - std::unique_lock lk(impl->scheduling_guard); - impl->current_fifo = nullptr; - auto it = impl->schedule_priority_queue.begin(); - while (it != impl->schedule_priority_queue.end()) { - pending_work = ScheduleLevel(it->second); - if (pending_work) { - break; - } - it = std::next(it); - } - if (pending_work) { - impl->must_reschedule = false; - } + while (UpdateHighestPriorityChannel()) { + impl->current_fifo->scheduled_count++; + Common::Fiber::YieldTo(impl->master_control, *impl->current_fifo->context); + } +} + +bool Scheduler::UpdateHighestPriorityChannel() { + std::scoped_lock lk(impl->scheduling_guard); + + // Clear needs to schedule state. + impl->must_reschedule = false; + + // By default, we don't have a channel to schedule. + impl->current_fifo = nullptr; + + // Check each level to see if we can schedule. + for (auto& level : impl->schedule_priority_queue) { + if (ScheduleLevel(level.second)) { + return true; } - if (impl->current_fifo) { - impl->current_fifo->scheduled_count++; - Common::Fiber::YieldTo(impl->master_control, *impl->current_fifo->context); - } - } while (pending_work); + } + + // Nothing to schedule. + return false; } bool Scheduler::ScheduleLevel(std::list& queue) { @@ -83,34 +85,48 @@ bool Scheduler::ScheduleLevel(std::list& queue) { size_t min_schedule_count = std::numeric_limits::max(); for (auto id : queue) { auto& fifo = impl->gpfifos[id]; - std::scoped_lock lk2(fifo.guard); - if (!fifo.pending_work.empty() || fifo.is_running) { - if (fifo.scheduled_count > min_schedule_count) { - continue; - } - if (fifo.scheduled_count < fifo.yield_count) { - fifo.scheduled_count++; - continue; - } - min_schedule_count = fifo.scheduled_count; - impl->current_fifo = &fifo; - found_anything = true; + std::scoped_lock lk(fifo.guard); + + // With no pending work and nothing running, this channel can't be scheduled. + if (fifo.pending_work.empty() && !fifo.is_running) { + continue; } + // Prioritize channels at current priority which have been run the least. + if (fifo.scheduled_count > min_schedule_count) { + continue; + } + + // Try not to select the same channel we just yielded from. + if (fifo.scheduled_count < fifo.yield_count) { + fifo.scheduled_count++; + continue; + } + + // Update best selection. + min_schedule_count = fifo.scheduled_count; + impl->current_fifo = &fifo; + found_anything = true; } return found_anything; } void Scheduler::ChangePriority(s32 channel_id, u32 new_priority) { - std::unique_lock lk(impl->scheduling_guard); + std::scoped_lock lk(impl->scheduling_guard); + // Ensure we are tracking this channel. auto fifo_it = impl->channel_gpfifo_ids.find(channel_id); if (fifo_it == impl->channel_gpfifo_ids.end()) { return; } + + // Get the fifo and update its priority. const size_t fifo_id = fifo_it->second; auto& fifo = impl->gpfifos[fifo_id]; - const auto old_priority = fifo.info->priority; - fifo.info->priority = new_priority; + const auto old_priority = std::exchange(fifo.info->priority, new_priority); + + // Create the new level if needed. impl->schedule_priority_queue.try_emplace(new_priority); + + // Remove the old level and add to the new level. impl->schedule_priority_queue[new_priority].push_back(fifo_id); impl->schedule_priority_queue[old_priority].remove_if( [fifo_id](size_t id) { return id == fifo_id; }); @@ -118,6 +134,8 @@ void Scheduler::ChangePriority(s32 channel_id, u32 new_priority) { void Scheduler::Yield() { ASSERT(impl->current_fifo != nullptr); + + // Set yield count higher impl->current_fifo->yield_count = impl->current_fifo->scheduled_count + 1; Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); gpu.BindChannel(impl->current_fifo->bind_id); @@ -126,50 +144,73 @@ void Scheduler::Yield() { void Scheduler::CheckStatus() { { std::unique_lock lk(impl->scheduling_guard); + // If no reschedule is needed, don't transfer control if (!impl->must_reschedule) { return; } } + // Transfer control to the scheduler Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); gpu.BindChannel(impl->current_fifo->bind_id); } void Scheduler::Push(s32 channel, CommandList&& entries) { - std::unique_lock lk(impl->scheduling_guard); + std::scoped_lock lk(impl->scheduling_guard); + // Get and ensure we have this channel. auto it = impl->channel_gpfifo_ids.find(channel); ASSERT(it != impl->channel_gpfifo_ids.end()); auto gpfifo_id = it->second; auto& fifo = impl->gpfifos[gpfifo_id]; + // Add the new new work to the channel. { std::scoped_lock lk2(fifo.guard); fifo.pending_work.emplace_back(std::move(entries)); } - if (impl->current_fifo != nullptr && impl->current_fifo->info->priority < fifo.info->priority) { - impl->must_reschedule = true; + + // If the current running FIFO is null or the one being pushed to then + // just return + if (impl->current_fifo == nullptr || impl->current_fifo == &fifo) { + return; } + + // If the current fifo has higher or equal priority to the current fifo then return + if (impl->current_fifo->info->priority >= fifo.info->priority) { + return; + } + // Mark scheduler update as required. + impl->must_reschedule = true; } void Scheduler::ChannelLoop(size_t gpfifo_id, s32 channel_id) { - gpu.BindChannel(channel_id); auto& fifo = impl->gpfifos[gpfifo_id]; - while (true) { - auto* channel_state = fifo.info.get(); - fifo.guard.lock(); - while (!fifo.pending_work.empty()) { - fifo.is_running = true; - { - CommandList&& entries = std::move(fifo.pending_work.front()); - channel_state->dma_pusher->Push(std::move(entries)); - fifo.pending_work.pop_front(); - } - fifo.guard.unlock(); - channel_state->dma_pusher->DispatchCalls(); - CheckStatus(); - fifo.guard.lock(); + auto* channel_state = fifo.info.get(); + const auto SendToPuller = [&] { + std::scoped_lock lk(fifo.guard); + if (fifo.pending_work.empty()) { + // Stop if no work available. + fifo.is_running = false; + return false; } - fifo.is_running = false; - fifo.guard.unlock(); + // Otherwise, send work to puller and mark as running. + CommandList&& entries = std::move(fifo.pending_work.front()); + channel_state->dma_pusher->Push(std::move(entries)); + fifo.pending_work.pop_front(); + fifo.is_running = true; + // Succeed. + return true; + }; + // Inform the GPU about the current channel. + gpu.BindChannel(channel_id); + while (true) { + while (SendToPuller()) { + // Execute. + channel_state->dma_pusher->DispatchCalls(); + // Reschedule. + CheckStatus(); + } + // Return to host execution when all work is completed. Common::Fiber::YieldTo(fifo.context, *impl->master_control); + // Inform the GPU about the current channel. gpu.BindChannel(channel_id); } } diff --git a/src/video_core/control/scheduler.h b/src/video_core/control/scheduler.h index faa888dde..9b5620499 100755 --- a/src/video_core/control/scheduler.h +++ b/src/video_core/control/scheduler.h @@ -39,6 +39,7 @@ private: void ChannelLoop(size_t gpfifo_id, s32 channel_id); bool ScheduleLevel(std::list& queue); void CheckStatus(); + bool UpdateHighestPriorityChannel(); struct SchedulerImpl; std::unique_ptr impl; diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 22eb7bd00..4cfaf7ce6 100755 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -42,6 +42,7 @@ ImageInfo::ImageInfo(const TICEntry& config) noexcept { }; } rescaleable = false; + is_sparse = config.is_sparse != 0; tile_width_spacing = config.tile_width_spacing; if (config.texture_type != TextureType::Texture2D && config.texture_type != TextureType::Texture2DNoMipmap) { diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 0a50795b3..286457acc 100755 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -41,6 +41,7 @@ struct ImageInfo { bool downscaleable = false; bool forced_flushed = false; bool dma_downloaded = false; + bool is_sparse = false; }; } // namespace VideoCommon diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index 85046e708..47ea0bd96 100755 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h @@ -600,17 +600,17 @@ void TextureCache

::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t siz [&](ImageId id, Image&) { deleted_images.push_back(id); }); for (const ImageId id : deleted_images) { Image& image = slot_images[id]; - if (True(image.flags & ImageFlagBits::CpuModified)) { - continue; + if (False(image.flags & ImageFlagBits::CpuModified)) { + image.flags |= ImageFlagBits::CpuModified; + if (True(image.flags & ImageFlagBits::Tracked)) { + UntrackImage(image, id); + } } - image.flags |= ImageFlagBits::CpuModified; + if (True(image.flags & ImageFlagBits::Remapped)) { continue; } image.flags |= ImageFlagBits::Remapped; - if (True(image.flags & ImageFlagBits::Tracked)) { - UntrackImage(image, id); - } } } @@ -1469,7 +1469,8 @@ ImageId TextureCache

::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); Image& new_image = slot_images[new_image_id]; - if (!gpu_memory->IsContinuousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { + if (!gpu_memory->IsContinuousRange(new_image.gpu_addr, new_image.guest_size_bytes) && + new_info.is_sparse) { new_image.flags |= ImageFlagBits::Sparse; } diff --git a/src/yuzu/hotkeys.cpp b/src/yuzu/hotkeys.cpp index 988bc7409..4bcc6ab04 100755 --- a/src/yuzu/hotkeys.cpp +++ b/src/yuzu/hotkeys.cpp @@ -190,10 +190,8 @@ void ControllerShortcut::ControllerUpdateEvent(Core::HID::ControllerTriggerType if (type != Core::HID::ControllerTriggerType::Button) { return; } - if (!Settings::values.controller_navigation) { - return; - } - if (button_sequence.npad.raw == Core::HID::NpadButton::None) { + if (button_sequence.npad.raw == Core::HID::NpadButton::None && + button_sequence.capture.raw == 0 && button_sequence.home.raw == 0) { return; }