diff options
author | pineappleEA <pineaea@gmail.com> | 2024-02-12 05:52:53 +0100 |
---|---|---|
committer | pineappleEA <pineaea@gmail.com> | 2024-02-12 05:52:53 +0100 |
commit | 765c7bb93a5d63d9ea54d1679f2d1b0c000d26f0 (patch) | |
tree | f2b93cfc2e2be9738117584c74ee8632d5d1e08b | |
parent | 9d83e9ad1b1431b81fab4b5bc84d3e9c1462d933 (diff) |
early-access version 4134EA-4134
-rwxr-xr-x | README.md | 2 | ||||
-rwxr-xr-x | src/core/hle/service/bcat/news/newly_arrived_event_holder.cpp | 2 | ||||
-rwxr-xr-x | src/core/hle/service/bcat/news/news_database_service.cpp | 24 | ||||
-rwxr-xr-x | src/core/hle/service/bcat/news/news_database_service.h | 8 | ||||
-rwxr-xr-x | src/core/hle/service/bcat/news/news_service.cpp | 17 | ||||
-rwxr-xr-x | src/core/hle/service/bcat/news/news_service.h | 4 | ||||
-rwxr-xr-x | src/core/hle/service/bcat/news/overwrite_event_holder.cpp | 2 | ||||
-rwxr-xr-x | src/core/hle/service/bcat/news/service_creator.cpp | 10 | ||||
-rwxr-xr-x | src/video_core/control/scheduler.cpp | 149 | ||||
-rwxr-xr-x | src/video_core/control/scheduler.h | 1 | ||||
-rwxr-xr-x | src/video_core/texture_cache/image_info.cpp | 1 | ||||
-rwxr-xr-x | src/video_core/texture_cache/image_info.h | 1 | ||||
-rwxr-xr-x | src/video_core/texture_cache/texture_cache.h | 15 | ||||
-rwxr-xr-x | src/yuzu/hotkeys.cpp | 6 |
14 files changed, 163 insertions, 79 deletions
@@ -1,7 +1,7 @@ | |||
1 | yuzu emulator early access | 1 | yuzu emulator early access |
2 | ============= | 2 | ============= |
3 | 3 | ||
4 | This is the source code for early-access 4132. | 4 | This is the source code for early-access 4134. |
5 | 5 | ||
6 | ## Legal Notice | 6 | ## Legal Notice |
7 | 7 | ||
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_) | |||
12 | "INewlyArrivedEventHolder"} { | 12 | "INewlyArrivedEventHolder"} { |
13 | // clang-format off | 13 | // clang-format off |
14 | static const FunctionInfo functions[] = { | 14 | static const FunctionInfo functions[] = { |
15 | {0, C<&INewlyArrivedEventHolder::Get>, "Get"}, | 15 | {0, D<&INewlyArrivedEventHolder::Get>, "Get"}, |
16 | }; | 16 | }; |
17 | // clang-format on | 17 | // clang-format on |
18 | 18 | ||
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_) | |||
11 | // clang-format off | 11 | // clang-format off |
12 | static const FunctionInfo functions[] = { | 12 | static const FunctionInfo functions[] = { |
13 | {0, nullptr, "GetListV1"}, | 13 | {0, nullptr, "GetListV1"}, |
14 | {1, C<&INewsDatabaseService::Count>, "Count"}, | 14 | {1, D<&INewsDatabaseService::Count>, "Count"}, |
15 | {2, nullptr, "CountWithKey"}, | 15 | {2, nullptr, "CountWithKey"}, |
16 | {3, nullptr, "UpdateIntegerValue"}, | 16 | {3, nullptr, "UpdateIntegerValue"}, |
17 | {4, nullptr, "UpdateIntegerValueWithAddition"}, | 17 | {4, D<&INewsDatabaseService::UpdateIntegerValueWithAddition>, "UpdateIntegerValueWithAddition"}, |
18 | {5, nullptr, "UpdateStringValue"}, | 18 | {5, nullptr, "UpdateStringValue"}, |
19 | {1000, nullptr, "GetList"}, | 19 | {1000, D<&INewsDatabaseService::GetList>, "GetList"}, |
20 | }; | 20 | }; |
21 | // clang-format on | 21 | // clang-format on |
22 | 22 | ||
@@ -32,4 +32,22 @@ Result INewsDatabaseService::Count(Out<s32> out_count, | |||
32 | R_SUCCEED(); | 32 | R_SUCCEED(); |
33 | } | 33 | } |
34 | 34 | ||
35 | Result INewsDatabaseService::UpdateIntegerValueWithAddition( | ||
36 | u32 value, InBuffer<BufferAttr_HipcPointer> buffer_data_1, | ||
37 | InBuffer<BufferAttr_HipcPointer> buffer_data_2) { | ||
38 | LOG_WARNING(Service_BCAT, "(STUBBED) called, value={}, buffer_size_1={}, buffer_data_2={}", | ||
39 | value, buffer_data_1.size(), buffer_data_2.size()); | ||
40 | R_SUCCEED(); | ||
41 | } | ||
42 | |||
43 | Result INewsDatabaseService::GetList(Out<s32> out_count, u32 value, | ||
44 | OutBuffer<BufferAttr_HipcMapAlias> out_buffer_data, | ||
45 | InBuffer<BufferAttr_HipcPointer> buffer_data_1, | ||
46 | InBuffer<BufferAttr_HipcPointer> buffer_data_2) { | ||
47 | LOG_WARNING(Service_BCAT, "(STUBBED) called, value={}, buffer_size_1={}, buffer_data_2={}", | ||
48 | value, buffer_data_1.size(), buffer_data_2.size()); | ||
49 | *out_count = 0; | ||
50 | R_SUCCEED(); | ||
51 | } | ||
52 | |||
35 | } // namespace Service::News | 53 | } // 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: | |||
19 | 19 | ||
20 | private: | 20 | private: |
21 | Result Count(Out<s32> out_count, InBuffer<BufferAttr_HipcPointer> buffer_data); | 21 | Result Count(Out<s32> out_count, InBuffer<BufferAttr_HipcPointer> buffer_data); |
22 | |||
23 | Result UpdateIntegerValueWithAddition(u32 value, InBuffer<BufferAttr_HipcPointer> buffer_data_1, | ||
24 | InBuffer<BufferAttr_HipcPointer> buffer_data_2); | ||
25 | |||
26 | Result GetList(Out<s32> out_count, u32 value, | ||
27 | OutBuffer<BufferAttr_HipcMapAlias> out_buffer_data, | ||
28 | InBuffer<BufferAttr_HipcPointer> buffer_data_1, | ||
29 | InBuffer<BufferAttr_HipcPointer> buffer_data_2); | ||
22 | }; | 30 | }; |
23 | 31 | ||
24 | } // namespace Service::News | 32 | } // 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 | |||
11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
12 | {10100, nullptr, "PostLocalNews"}, | 12 | {10100, nullptr, "PostLocalNews"}, |
13 | {20100, nullptr, "SetPassphrase"}, | 13 | {20100, nullptr, "SetPassphrase"}, |
14 | {30100, C<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"}, | 14 | {30100, D<&INewsService::GetSubscriptionStatus>, "GetSubscriptionStatus"}, |
15 | {30101, nullptr, "GetTopicList"}, | 15 | {30101, nullptr, "GetTopicList"}, |
16 | {30110, nullptr, "Unknown30110"}, | 16 | {30110, nullptr, "Unknown30110"}, |
17 | {30200, nullptr, "IsSystemUpdateRequired"}, | 17 | {30200, D<&INewsService::IsSystemUpdateRequired>, "IsSystemUpdateRequired"}, |
18 | {30201, nullptr, "Unknown30201"}, | 18 | {30201, nullptr, "Unknown30201"}, |
19 | {30210, nullptr, "Unknown30210"}, | 19 | {30210, nullptr, "Unknown30210"}, |
20 | {30300, nullptr, "RequestImmediateReception"}, | 20 | {30300, nullptr, "RequestImmediateReception"}, |
@@ -24,7 +24,7 @@ INewsService::INewsService(Core::System& system_) : ServiceFramework{system_, "I | |||
24 | {30901, nullptr, "Unknown30901"}, | 24 | {30901, nullptr, "Unknown30901"}, |
25 | {30902, nullptr, "Unknown30902"}, | 25 | {30902, nullptr, "Unknown30902"}, |
26 | {40100, nullptr, "SetSubscriptionStatus"}, | 26 | {40100, nullptr, "SetSubscriptionStatus"}, |
27 | {40101, nullptr, "RequestAutoSubscription"}, | 27 | {40101, D<&INewsService::RequestAutoSubscription>, "RequestAutoSubscription"}, |
28 | {40200, nullptr, "ClearStorage"}, | 28 | {40200, nullptr, "ClearStorage"}, |
29 | {40201, nullptr, "ClearSubscriptionStatusAll"}, | 29 | {40201, nullptr, "ClearSubscriptionStatusAll"}, |
30 | {90100, nullptr, "GetNewsDatabaseDump"}, | 30 | {90100, nullptr, "GetNewsDatabaseDump"}, |
@@ -43,4 +43,15 @@ Result INewsService::GetSubscriptionStatus(Out<u32> out_status, | |||
43 | R_SUCCEED(); | 43 | R_SUCCEED(); |
44 | } | 44 | } |
45 | 45 | ||
46 | Result INewsService::IsSystemUpdateRequired(Out<bool> out_is_system_update_required) { | ||
47 | LOG_WARNING(Service_BCAT, "(STUBBED) called"); | ||
48 | *out_is_system_update_required = false; | ||
49 | R_SUCCEED(); | ||
50 | } | ||
51 | |||
52 | Result INewsService::RequestAutoSubscription(u64 value) { | ||
53 | LOG_WARNING(Service_BCAT, "(STUBBED) called"); | ||
54 | R_SUCCEED(); | ||
55 | } | ||
56 | |||
46 | } // namespace Service::News | 57 | } // 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: | |||
19 | 19 | ||
20 | private: | 20 | private: |
21 | Result GetSubscriptionStatus(Out<u32> out_status, InBuffer<BufferAttr_HipcPointer> buffer_data); | 21 | Result GetSubscriptionStatus(Out<u32> out_status, InBuffer<BufferAttr_HipcPointer> buffer_data); |
22 | |||
23 | Result IsSystemUpdateRequired(Out<bool> out_is_system_update_required); | ||
24 | |||
25 | Result RequestAutoSubscription(u64 value); | ||
22 | }; | 26 | }; |
23 | 27 | ||
24 | } // namespace Service::News | 28 | } // 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_) | |||
11 | "IOverwriteEventHolder"} { | 11 | "IOverwriteEventHolder"} { |
12 | // clang-format off | 12 | // clang-format off |
13 | static const FunctionInfo functions[] = { | 13 | static const FunctionInfo functions[] = { |
14 | {0, C<&IOverwriteEventHolder::Get>, "Get"}, | 14 | {0, D<&IOverwriteEventHolder::Get>, "Get"}, |
15 | }; | 15 | }; |
16 | // clang-format on | 16 | // clang-format on |
17 | 17 | ||
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 | |||
15 | : ServiceFramework{system_, name_}, permissions{permissions_} { | 15 | : ServiceFramework{system_, name_}, permissions{permissions_} { |
16 | // clang-format off | 16 | // clang-format off |
17 | static const FunctionInfo functions[] = { | 17 | static const FunctionInfo functions[] = { |
18 | {0, C<&IServiceCreator::CreateNewsService>, "CreateNewsService"}, | 18 | {0, D<&IServiceCreator::CreateNewsService>, "CreateNewsService"}, |
19 | {1, C<&IServiceCreator::CreateNewlyArrivedEventHolder>, "CreateNewlyArrivedEventHolder"}, | 19 | {1, D<&IServiceCreator::CreateNewlyArrivedEventHolder>, "CreateNewlyArrivedEventHolder"}, |
20 | {2, C<&IServiceCreator::CreateNewsDataService>, "CreateNewsDataService"}, | 20 | {2, D<&IServiceCreator::CreateNewsDataService>, "CreateNewsDataService"}, |
21 | {3, C<&IServiceCreator::CreateNewsDatabaseService>, "CreateNewsDatabaseService"}, | 21 | {3, D<&IServiceCreator::CreateNewsDatabaseService>, "CreateNewsDatabaseService"}, |
22 | {4, C<&IServiceCreator::CreateOverwriteEventHolder>, "CreateOverwriteEventHolder"}, | 22 | {4, D<&IServiceCreator::CreateOverwriteEventHolder>, "CreateOverwriteEventHolder"}, |
23 | }; | 23 | }; |
24 | // clang-format on | 24 | // clang-format on |
25 | 25 | ||
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 @@ | |||
7 | #include <memory> | 7 | #include <memory> |
8 | #include <mutex> | 8 | #include <mutex> |
9 | #include <unordered_map> | 9 | #include <unordered_map> |
10 | #include <utility> | ||
10 | 11 | ||
11 | #include "common/assert.h" | 12 | #include "common/assert.h" |
12 | #include "common/fiber.h" | 13 | #include "common/fiber.h" |
@@ -53,29 +54,30 @@ void Scheduler::Init() { | |||
53 | } | 54 | } |
54 | 55 | ||
55 | void Scheduler::Resume() { | 56 | void Scheduler::Resume() { |
56 | bool pending_work; | 57 | while (UpdateHighestPriorityChannel()) { |
57 | do { | 58 | impl->current_fifo->scheduled_count++; |
58 | pending_work = false; | 59 | Common::Fiber::YieldTo(impl->master_control, *impl->current_fifo->context); |
59 | { | 60 | } |
60 | std::unique_lock lk(impl->scheduling_guard); | 61 | } |
61 | impl->current_fifo = nullptr; | 62 | |
62 | auto it = impl->schedule_priority_queue.begin(); | 63 | bool Scheduler::UpdateHighestPriorityChannel() { |
63 | while (it != impl->schedule_priority_queue.end()) { | 64 | std::scoped_lock lk(impl->scheduling_guard); |
64 | pending_work = ScheduleLevel(it->second); | 65 | |
65 | if (pending_work) { | 66 | // Clear needs to schedule state. |
66 | break; | 67 | impl->must_reschedule = false; |
67 | } | 68 | |
68 | it = std::next(it); | 69 | // By default, we don't have a channel to schedule. |
69 | } | 70 | impl->current_fifo = nullptr; |
70 | if (pending_work) { | 71 | |
71 | impl->must_reschedule = false; | 72 | // Check each level to see if we can schedule. |
72 | } | 73 | for (auto& level : impl->schedule_priority_queue) { |
73 | } | 74 | if (ScheduleLevel(level.second)) { |
74 | if (impl->current_fifo) { | 75 | return true; |
75 | impl->current_fifo->scheduled_count++; | ||
76 | Common::Fiber::YieldTo(impl->master_control, *impl->current_fifo->context); | ||
77 | } | 76 | } |
78 | } while (pending_work); | 77 | } |
78 | |||
79 | // Nothing to schedule. | ||
80 | return false; | ||
79 | } | 81 | } |
80 | 82 | ||
81 | bool Scheduler::ScheduleLevel(std::list<size_t>& queue) { | 83 | bool Scheduler::ScheduleLevel(std::list<size_t>& queue) { |
@@ -83,34 +85,48 @@ bool Scheduler::ScheduleLevel(std::list<size_t>& queue) { | |||
83 | size_t min_schedule_count = std::numeric_limits<size_t>::max(); | 85 | size_t min_schedule_count = std::numeric_limits<size_t>::max(); |
84 | for (auto id : queue) { | 86 | for (auto id : queue) { |
85 | auto& fifo = impl->gpfifos[id]; | 87 | auto& fifo = impl->gpfifos[id]; |
86 | std::scoped_lock lk2(fifo.guard); | 88 | std::scoped_lock lk(fifo.guard); |
87 | if (!fifo.pending_work.empty() || fifo.is_running) { | 89 | |
88 | if (fifo.scheduled_count > min_schedule_count) { | 90 | // With no pending work and nothing running, this channel can't be scheduled. |
89 | continue; | 91 | if (fifo.pending_work.empty() && !fifo.is_running) { |
90 | } | 92 | continue; |
91 | if (fifo.scheduled_count < fifo.yield_count) { | 93 | } |
92 | fifo.scheduled_count++; | 94 | // Prioritize channels at current priority which have been run the least. |
93 | continue; | 95 | if (fifo.scheduled_count > min_schedule_count) { |
94 | } | 96 | continue; |
95 | min_schedule_count = fifo.scheduled_count; | ||
96 | impl->current_fifo = &fifo; | ||
97 | found_anything = true; | ||
98 | } | 97 | } |
98 | |||
99 | // Try not to select the same channel we just yielded from. | ||
100 | if (fifo.scheduled_count < fifo.yield_count) { | ||
101 | fifo.scheduled_count++; | ||
102 | continue; | ||
103 | } | ||
104 | |||
105 | // Update best selection. | ||
106 | min_schedule_count = fifo.scheduled_count; | ||
107 | impl->current_fifo = &fifo; | ||
108 | found_anything = true; | ||
99 | } | 109 | } |
100 | return found_anything; | 110 | return found_anything; |
101 | } | 111 | } |
102 | 112 | ||
103 | void Scheduler::ChangePriority(s32 channel_id, u32 new_priority) { | 113 | void Scheduler::ChangePriority(s32 channel_id, u32 new_priority) { |
104 | std::unique_lock lk(impl->scheduling_guard); | 114 | std::scoped_lock lk(impl->scheduling_guard); |
115 | // Ensure we are tracking this channel. | ||
105 | auto fifo_it = impl->channel_gpfifo_ids.find(channel_id); | 116 | auto fifo_it = impl->channel_gpfifo_ids.find(channel_id); |
106 | if (fifo_it == impl->channel_gpfifo_ids.end()) { | 117 | if (fifo_it == impl->channel_gpfifo_ids.end()) { |
107 | return; | 118 | return; |
108 | } | 119 | } |
120 | |||
121 | // Get the fifo and update its priority. | ||
109 | const size_t fifo_id = fifo_it->second; | 122 | const size_t fifo_id = fifo_it->second; |
110 | auto& fifo = impl->gpfifos[fifo_id]; | 123 | auto& fifo = impl->gpfifos[fifo_id]; |
111 | const auto old_priority = fifo.info->priority; | 124 | const auto old_priority = std::exchange(fifo.info->priority, new_priority); |
112 | fifo.info->priority = new_priority; | 125 | |
126 | // Create the new level if needed. | ||
113 | impl->schedule_priority_queue.try_emplace(new_priority); | 127 | impl->schedule_priority_queue.try_emplace(new_priority); |
128 | |||
129 | // Remove the old level and add to the new level. | ||
114 | impl->schedule_priority_queue[new_priority].push_back(fifo_id); | 130 | impl->schedule_priority_queue[new_priority].push_back(fifo_id); |
115 | impl->schedule_priority_queue[old_priority].remove_if( | 131 | impl->schedule_priority_queue[old_priority].remove_if( |
116 | [fifo_id](size_t id) { return id == fifo_id; }); | 132 | [fifo_id](size_t id) { return id == fifo_id; }); |
@@ -118,6 +134,8 @@ void Scheduler::ChangePriority(s32 channel_id, u32 new_priority) { | |||
118 | 134 | ||
119 | void Scheduler::Yield() { | 135 | void Scheduler::Yield() { |
120 | ASSERT(impl->current_fifo != nullptr); | 136 | ASSERT(impl->current_fifo != nullptr); |
137 | |||
138 | // Set yield count higher | ||
121 | impl->current_fifo->yield_count = impl->current_fifo->scheduled_count + 1; | 139 | impl->current_fifo->yield_count = impl->current_fifo->scheduled_count + 1; |
122 | Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); | 140 | Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); |
123 | gpu.BindChannel(impl->current_fifo->bind_id); | 141 | gpu.BindChannel(impl->current_fifo->bind_id); |
@@ -126,50 +144,73 @@ void Scheduler::Yield() { | |||
126 | void Scheduler::CheckStatus() { | 144 | void Scheduler::CheckStatus() { |
127 | { | 145 | { |
128 | std::unique_lock lk(impl->scheduling_guard); | 146 | std::unique_lock lk(impl->scheduling_guard); |
147 | // If no reschedule is needed, don't transfer control | ||
129 | if (!impl->must_reschedule) { | 148 | if (!impl->must_reschedule) { |
130 | return; | 149 | return; |
131 | } | 150 | } |
132 | } | 151 | } |
152 | // Transfer control to the scheduler | ||
133 | Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); | 153 | Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); |
134 | gpu.BindChannel(impl->current_fifo->bind_id); | 154 | gpu.BindChannel(impl->current_fifo->bind_id); |
135 | } | 155 | } |
136 | 156 | ||
137 | void Scheduler::Push(s32 channel, CommandList&& entries) { | 157 | void Scheduler::Push(s32 channel, CommandList&& entries) { |
138 | std::unique_lock lk(impl->scheduling_guard); | 158 | std::scoped_lock lk(impl->scheduling_guard); |
159 | // Get and ensure we have this channel. | ||
139 | auto it = impl->channel_gpfifo_ids.find(channel); | 160 | auto it = impl->channel_gpfifo_ids.find(channel); |
140 | ASSERT(it != impl->channel_gpfifo_ids.end()); | 161 | ASSERT(it != impl->channel_gpfifo_ids.end()); |
141 | auto gpfifo_id = it->second; | 162 | auto gpfifo_id = it->second; |
142 | auto& fifo = impl->gpfifos[gpfifo_id]; | 163 | auto& fifo = impl->gpfifos[gpfifo_id]; |
164 | // Add the new new work to the channel. | ||
143 | { | 165 | { |
144 | std::scoped_lock lk2(fifo.guard); | 166 | std::scoped_lock lk2(fifo.guard); |
145 | fifo.pending_work.emplace_back(std::move(entries)); | 167 | fifo.pending_work.emplace_back(std::move(entries)); |
146 | } | 168 | } |
147 | if (impl->current_fifo != nullptr && impl->current_fifo->info->priority < fifo.info->priority) { | 169 | |
148 | impl->must_reschedule = true; | 170 | // If the current running FIFO is null or the one being pushed to then |
171 | // just return | ||
172 | if (impl->current_fifo == nullptr || impl->current_fifo == &fifo) { | ||
173 | return; | ||
174 | } | ||
175 | |||
176 | // If the current fifo has higher or equal priority to the current fifo then return | ||
177 | if (impl->current_fifo->info->priority >= fifo.info->priority) { | ||
178 | return; | ||
149 | } | 179 | } |
180 | // Mark scheduler update as required. | ||
181 | impl->must_reschedule = true; | ||
150 | } | 182 | } |
151 | 183 | ||
152 | void Scheduler::ChannelLoop(size_t gpfifo_id, s32 channel_id) { | 184 | void Scheduler::ChannelLoop(size_t gpfifo_id, s32 channel_id) { |
153 | gpu.BindChannel(channel_id); | ||
154 | auto& fifo = impl->gpfifos[gpfifo_id]; | 185 | auto& fifo = impl->gpfifos[gpfifo_id]; |
186 | auto* channel_state = fifo.info.get(); | ||
187 | const auto SendToPuller = [&] { | ||
188 | std::scoped_lock lk(fifo.guard); | ||
189 | if (fifo.pending_work.empty()) { | ||
190 | // Stop if no work available. | ||
191 | fifo.is_running = false; | ||
192 | return false; | ||
193 | } | ||
194 | // Otherwise, send work to puller and mark as running. | ||
195 | CommandList&& entries = std::move(fifo.pending_work.front()); | ||
196 | channel_state->dma_pusher->Push(std::move(entries)); | ||
197 | fifo.pending_work.pop_front(); | ||
198 | fifo.is_running = true; | ||
199 | // Succeed. | ||
200 | return true; | ||
201 | }; | ||
202 | // Inform the GPU about the current channel. | ||
203 | gpu.BindChannel(channel_id); | ||
155 | while (true) { | 204 | while (true) { |
156 | auto* channel_state = fifo.info.get(); | 205 | while (SendToPuller()) { |
157 | fifo.guard.lock(); | 206 | // Execute. |
158 | while (!fifo.pending_work.empty()) { | ||
159 | fifo.is_running = true; | ||
160 | { | ||
161 | CommandList&& entries = std::move(fifo.pending_work.front()); | ||
162 | channel_state->dma_pusher->Push(std::move(entries)); | ||
163 | fifo.pending_work.pop_front(); | ||
164 | } | ||
165 | fifo.guard.unlock(); | ||
166 | channel_state->dma_pusher->DispatchCalls(); | 207 | channel_state->dma_pusher->DispatchCalls(); |
208 | // Reschedule. | ||
167 | CheckStatus(); | 209 | CheckStatus(); |
168 | fifo.guard.lock(); | ||
169 | } | 210 | } |
170 | fifo.is_running = false; | 211 | // Return to host execution when all work is completed. |
171 | fifo.guard.unlock(); | ||
172 | Common::Fiber::YieldTo(fifo.context, *impl->master_control); | 212 | Common::Fiber::YieldTo(fifo.context, *impl->master_control); |
213 | // Inform the GPU about the current channel. | ||
173 | gpu.BindChannel(channel_id); | 214 | gpu.BindChannel(channel_id); |
174 | } | 215 | } |
175 | } | 216 | } |
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: | |||
39 | void ChannelLoop(size_t gpfifo_id, s32 channel_id); | 39 | void ChannelLoop(size_t gpfifo_id, s32 channel_id); |
40 | bool ScheduleLevel(std::list<size_t>& queue); | 40 | bool ScheduleLevel(std::list<size_t>& queue); |
41 | void CheckStatus(); | 41 | void CheckStatus(); |
42 | bool UpdateHighestPriorityChannel(); | ||
42 | 43 | ||
43 | struct SchedulerImpl; | 44 | struct SchedulerImpl; |
44 | std::unique_ptr<SchedulerImpl> impl; | 45 | std::unique_ptr<SchedulerImpl> 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 { | |||
42 | }; | 42 | }; |
43 | } | 43 | } |
44 | rescaleable = false; | 44 | rescaleable = false; |
45 | is_sparse = config.is_sparse != 0; | ||
45 | tile_width_spacing = config.tile_width_spacing; | 46 | tile_width_spacing = config.tile_width_spacing; |
46 | if (config.texture_type != TextureType::Texture2D && | 47 | if (config.texture_type != TextureType::Texture2D && |
47 | config.texture_type != TextureType::Texture2DNoMipmap) { | 48 | 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 { | |||
41 | bool downscaleable = false; | 41 | bool downscaleable = false; |
42 | bool forced_flushed = false; | 42 | bool forced_flushed = false; |
43 | bool dma_downloaded = false; | 43 | bool dma_downloaded = false; |
44 | bool is_sparse = false; | ||
44 | }; | 45 | }; |
45 | 46 | ||
46 | } // namespace VideoCommon | 47 | } // 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<P>::UnmapGPUMemory(size_t as_id, GPUVAddr gpu_addr, size_t siz | |||
600 | [&](ImageId id, Image&) { deleted_images.push_back(id); }); | 600 | [&](ImageId id, Image&) { deleted_images.push_back(id); }); |
601 | for (const ImageId id : deleted_images) { | 601 | for (const ImageId id : deleted_images) { |
602 | Image& image = slot_images[id]; | 602 | Image& image = slot_images[id]; |
603 | if (True(image.flags & ImageFlagBits::CpuModified)) { | 603 | if (False(image.flags & ImageFlagBits::CpuModified)) { |
604 | continue; | 604 | image.flags |= ImageFlagBits::CpuModified; |
605 | if (True(image.flags & ImageFlagBits::Tracked)) { | ||
606 | UntrackImage(image, id); | ||
607 | } | ||
605 | } | 608 | } |
606 | image.flags |= ImageFlagBits::CpuModified; | 609 | |
607 | if (True(image.flags & ImageFlagBits::Remapped)) { | 610 | if (True(image.flags & ImageFlagBits::Remapped)) { |
608 | continue; | 611 | continue; |
609 | } | 612 | } |
610 | image.flags |= ImageFlagBits::Remapped; | 613 | image.flags |= ImageFlagBits::Remapped; |
611 | if (True(image.flags & ImageFlagBits::Tracked)) { | ||
612 | UntrackImage(image, id); | ||
613 | } | ||
614 | } | 614 | } |
615 | } | 615 | } |
616 | 616 | ||
@@ -1469,7 +1469,8 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, DA | |||
1469 | const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); | 1469 | const ImageId new_image_id = slot_images.insert(runtime, new_info, gpu_addr, cpu_addr); |
1470 | Image& new_image = slot_images[new_image_id]; | 1470 | Image& new_image = slot_images[new_image_id]; |
1471 | 1471 | ||
1472 | if (!gpu_memory->IsContinuousRange(new_image.gpu_addr, new_image.guest_size_bytes)) { | 1472 | if (!gpu_memory->IsContinuousRange(new_image.gpu_addr, new_image.guest_size_bytes) && |
1473 | new_info.is_sparse) { | ||
1473 | new_image.flags |= ImageFlagBits::Sparse; | 1474 | new_image.flags |= ImageFlagBits::Sparse; |
1474 | } | 1475 | } |
1475 | 1476 | ||
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 | |||
190 | if (type != Core::HID::ControllerTriggerType::Button) { | 190 | if (type != Core::HID::ControllerTriggerType::Button) { |
191 | return; | 191 | return; |
192 | } | 192 | } |
193 | if (!Settings::values.controller_navigation) { | 193 | if (button_sequence.npad.raw == Core::HID::NpadButton::None && |
194 | return; | 194 | button_sequence.capture.raw == 0 && button_sequence.home.raw == 0) { |
195 | } | ||
196 | if (button_sequence.npad.raw == Core::HID::NpadButton::None) { | ||
197 | return; | 195 | return; |
198 | } | 196 | } |
199 | 197 | ||