diff options
author | pineappleEA <pineaea@gmail.com> | 2024-02-21 02:52:05 +0100 |
---|---|---|
committer | pineappleEA <pineaea@gmail.com> | 2024-02-21 02:52:05 +0100 |
commit | b86c4f1e6680f971f0979c0544e7e20fa1145fa3 (patch) | |
tree | 057642926928c7b14c95082e56b8734318a79bb6 | |
parent | 64bd48fad59e60a5fa48c8ce512fbe80ff532e90 (diff) |
early-access version 4155EA-4155
24 files changed, 160 insertions, 298 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 4154. | 4 | This is the source code for early-access 4155. |
5 | 5 | ||
6 | ## Legal Notice | 6 | ## Legal Notice |
7 | 7 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt index a0d8cfede..6f16cf5b1 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/StringSetting.kt | |||
@@ -6,7 +6,8 @@ package org.yuzu.yuzu_emu.features.settings.model | |||
6 | import org.yuzu.yuzu_emu.utils.NativeConfig | 6 | import org.yuzu.yuzu_emu.utils.NativeConfig |
7 | 7 | ||
8 | enum class StringSetting(override val key: String) : AbstractStringSetting { | 8 | enum class StringSetting(override val key: String) : AbstractStringSetting { |
9 | DRIVER_PATH("driver_path"); | 9 | DRIVER_PATH("driver_path"), |
10 | DEVICE_NAME("device_name"); | ||
10 | 11 | ||
11 | override fun getString(needsGlobal: Boolean): String = NativeConfig.getString(key, needsGlobal) | 12 | override fun getString(needsGlobal: Boolean): String = NativeConfig.getString(key, needsGlobal) |
12 | 13 | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt index 03d81ceb3..5fdf98318 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt | |||
@@ -16,6 +16,7 @@ import org.yuzu.yuzu_emu.features.settings.model.ByteSetting | |||
16 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting | 16 | import org.yuzu.yuzu_emu.features.settings.model.IntSetting |
17 | import org.yuzu.yuzu_emu.features.settings.model.LongSetting | 17 | import org.yuzu.yuzu_emu.features.settings.model.LongSetting |
18 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting | 18 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting |
19 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting | ||
19 | import org.yuzu.yuzu_emu.utils.NativeConfig | 20 | import org.yuzu.yuzu_emu.utils.NativeConfig |
20 | 21 | ||
21 | /** | 22 | /** |
@@ -90,6 +91,7 @@ abstract class SettingsItem( | |||
90 | const val TYPE_INPUT = 8 | 91 | const val TYPE_INPUT = 8 |
91 | const val TYPE_INT_SINGLE_CHOICE = 9 | 92 | const val TYPE_INT_SINGLE_CHOICE = 9 |
92 | const val TYPE_INPUT_PROFILE = 10 | 93 | const val TYPE_INPUT_PROFILE = 10 |
94 | const val TYPE_STRING_INPUT = 11 | ||
93 | 95 | ||
94 | const val FASTMEM_COMBINED = "fastmem_combined" | 96 | const val FASTMEM_COMBINED = "fastmem_combined" |
95 | 97 | ||
@@ -108,6 +110,7 @@ abstract class SettingsItem( | |||
108 | 110 | ||
109 | // List of all general | 111 | // List of all general |
110 | val settingsItems = HashMap<String, SettingsItem>().apply { | 112 | val settingsItems = HashMap<String, SettingsItem>().apply { |
113 | put(StringInputSetting(StringSetting.DEVICE_NAME, titleId = R.string.device_name)) | ||
111 | put( | 114 | put( |
112 | SwitchSetting( | 115 | SwitchSetting( |
113 | BooleanSetting.RENDERER_USE_SPEED_LIMIT, | 116 | BooleanSetting.RENDERER_USE_SPEED_LIMIT, |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt new file mode 100755 index 000000000..1eb999416 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringInputSetting.kt | |||
@@ -0,0 +1,22 @@ | |||
1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | package org.yuzu.yuzu_emu.features.settings.model.view | ||
5 | |||
6 | import androidx.annotation.StringRes | ||
7 | import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting | ||
8 | |||
9 | class StringInputSetting( | ||
10 | setting: AbstractStringSetting, | ||
11 | @StringRes titleId: Int = 0, | ||
12 | titleString: String = "", | ||
13 | @StringRes descriptionId: Int = 0, | ||
14 | descriptionString: String = "" | ||
15 | ) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) { | ||
16 | override val type = TYPE_STRING_INPUT | ||
17 | |||
18 | fun getSelectedValue(needsGlobal: Boolean = false) = setting.getValueAsString(needsGlobal) | ||
19 | |||
20 | fun setSelectedValue(selection: String) = | ||
21 | (setting as AbstractStringSetting).setString(selection) | ||
22 | } | ||
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt index 45c8faa10..500ac6e66 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsAdapter.kt | |||
@@ -85,6 +85,10 @@ class SettingsAdapter( | |||
85 | InputProfileViewHolder(ListItemSettingBinding.inflate(inflater), this) | 85 | InputProfileViewHolder(ListItemSettingBinding.inflate(inflater), this) |
86 | } | 86 | } |
87 | 87 | ||
88 | SettingsItem.TYPE_STRING_INPUT -> { | ||
89 | StringInputViewHolder(ListItemSettingBinding.inflate(inflater), this) | ||
90 | } | ||
91 | |||
88 | else -> { | 92 | else -> { |
89 | HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this) | 93 | HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this) |
90 | } | 94 | } |
@@ -392,6 +396,15 @@ class SettingsAdapter( | |||
392 | popup.show() | 396 | popup.show() |
393 | } | 397 | } |
394 | 398 | ||
399 | fun onStringInputClick(item: StringInputSetting, position: Int) { | ||
400 | SettingsDialogFragment.newInstance( | ||
401 | settingsViewModel, | ||
402 | item, | ||
403 | SettingsItem.TYPE_STRING_INPUT, | ||
404 | position | ||
405 | ).show(fragment.childFragmentManager, SettingsDialogFragment.TAG) | ||
406 | } | ||
407 | |||
395 | fun onLongClick(item: SettingsItem, position: Int): Boolean { | 408 | fun onLongClick(item: SettingsItem, position: Int): Boolean { |
396 | SettingsDialogFragment.newInstance( | 409 | SettingsDialogFragment.newInstance( |
397 | settingsViewModel, | 410 | settingsViewModel, |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt index a81ff6b1a..7f562a1f4 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsDialogFragment.kt | |||
@@ -14,6 +14,7 @@ import androidx.fragment.app.activityViewModels | |||
14 | import com.google.android.material.dialog.MaterialAlertDialogBuilder | 14 | import com.google.android.material.dialog.MaterialAlertDialogBuilder |
15 | import com.google.android.material.slider.Slider | 15 | import com.google.android.material.slider.Slider |
16 | import org.yuzu.yuzu_emu.R | 16 | import org.yuzu.yuzu_emu.R |
17 | import org.yuzu.yuzu_emu.databinding.DialogEditTextBinding | ||
17 | import org.yuzu.yuzu_emu.databinding.DialogSliderBinding | 18 | import org.yuzu.yuzu_emu.databinding.DialogSliderBinding |
18 | import org.yuzu.yuzu_emu.features.input.NativeInput | 19 | import org.yuzu.yuzu_emu.features.input.NativeInput |
19 | import org.yuzu.yuzu_emu.features.input.model.AnalogDirection | 20 | import org.yuzu.yuzu_emu.features.input.model.AnalogDirection |
@@ -23,6 +24,7 @@ import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting | |||
23 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem | 24 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem |
24 | import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting | 25 | import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting |
25 | import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting | 26 | import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting |
27 | import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting | ||
26 | import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting | 28 | import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting |
27 | import org.yuzu.yuzu_emu.utils.ParamPackage | 29 | import org.yuzu.yuzu_emu.utils.ParamPackage |
28 | import org.yuzu.yuzu_emu.utils.collect | 30 | import org.yuzu.yuzu_emu.utils.collect |
@@ -37,6 +39,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener | |||
37 | private val settingsViewModel: SettingsViewModel by activityViewModels() | 39 | private val settingsViewModel: SettingsViewModel by activityViewModels() |
38 | 40 | ||
39 | private lateinit var sliderBinding: DialogSliderBinding | 41 | private lateinit var sliderBinding: DialogSliderBinding |
42 | private lateinit var stringInputBinding: DialogEditTextBinding | ||
40 | 43 | ||
41 | override fun onCreate(savedInstanceState: Bundle?) { | 44 | override fun onCreate(savedInstanceState: Bundle?) { |
42 | super.onCreate(savedInstanceState) | 45 | super.onCreate(savedInstanceState) |
@@ -131,6 +134,18 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener | |||
131 | .create() | 134 | .create() |
132 | } | 135 | } |
133 | 136 | ||
137 | SettingsItem.TYPE_STRING_INPUT -> { | ||
138 | stringInputBinding = DialogEditTextBinding.inflate(layoutInflater) | ||
139 | val item = settingsViewModel.clickedItem as StringInputSetting | ||
140 | stringInputBinding.editText.setText(item.getSelectedValue()) | ||
141 | MaterialAlertDialogBuilder(requireContext()) | ||
142 | .setTitle(item.title) | ||
143 | .setView(stringInputBinding.root) | ||
144 | .setPositiveButton(android.R.string.ok, this) | ||
145 | .setNegativeButton(android.R.string.cancel, defaultCancelListener) | ||
146 | .create() | ||
147 | } | ||
148 | |||
134 | SettingsItem.TYPE_STRING_SINGLE_CHOICE -> { | 149 | SettingsItem.TYPE_STRING_SINGLE_CHOICE -> { |
135 | val item = settingsViewModel.clickedItem as StringSingleChoiceSetting | 150 | val item = settingsViewModel.clickedItem as StringSingleChoiceSetting |
136 | MaterialAlertDialogBuilder(requireContext()) | 151 | MaterialAlertDialogBuilder(requireContext()) |
@@ -158,6 +173,7 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener | |||
158 | ): View? { | 173 | ): View? { |
159 | return when (type) { | 174 | return when (type) { |
160 | SettingsItem.TYPE_SLIDER -> sliderBinding.root | 175 | SettingsItem.TYPE_SLIDER -> sliderBinding.root |
176 | SettingsItem.TYPE_STRING_INPUT -> stringInputBinding.root | ||
161 | else -> super.onCreateView(inflater, container, savedInstanceState) | 177 | else -> super.onCreateView(inflater, container, savedInstanceState) |
162 | } | 178 | } |
163 | } | 179 | } |
@@ -200,6 +216,13 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener | |||
200 | val sliderSetting = settingsViewModel.clickedItem as SliderSetting | 216 | val sliderSetting = settingsViewModel.clickedItem as SliderSetting |
201 | sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value) | 217 | sliderSetting.setSelectedValue(settingsViewModel.sliderProgress.value) |
202 | } | 218 | } |
219 | |||
220 | is StringInputSetting -> { | ||
221 | val stringInputSetting = settingsViewModel.clickedItem as StringInputSetting | ||
222 | stringInputSetting.setSelectedValue( | ||
223 | (stringInputBinding.editText.text ?: "").toString() | ||
224 | ) | ||
225 | } | ||
203 | } | 226 | } |
204 | closeDialog() | 227 | closeDialog() |
205 | } | 228 | } |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt index e491c29a2..6907bec02 100755 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt | |||
@@ -23,6 +23,7 @@ import org.yuzu.yuzu_emu.features.settings.model.LongSetting | |||
23 | import org.yuzu.yuzu_emu.features.settings.model.Settings | 23 | import org.yuzu.yuzu_emu.features.settings.model.Settings |
24 | import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag | 24 | import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag |
25 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting | 25 | import org.yuzu.yuzu_emu.features.settings.model.ShortSetting |
26 | import org.yuzu.yuzu_emu.features.settings.model.StringSetting | ||
26 | import org.yuzu.yuzu_emu.features.settings.model.view.* | 27 | import org.yuzu.yuzu_emu.features.settings.model.view.* |
27 | import org.yuzu.yuzu_emu.utils.InputHandler | 28 | import org.yuzu.yuzu_emu.utils.InputHandler |
28 | import org.yuzu.yuzu_emu.utils.NativeConfig | 29 | import org.yuzu.yuzu_emu.utils.NativeConfig |
@@ -153,6 +154,7 @@ class SettingsFragmentPresenter( | |||
153 | 154 | ||
154 | private fun addSystemSettings(sl: ArrayList<SettingsItem>) { | 155 | private fun addSystemSettings(sl: ArrayList<SettingsItem>) { |
155 | sl.apply { | 156 | sl.apply { |
157 | add(StringSetting.DEVICE_NAME.key) | ||
156 | add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key) | 158 | add(BooleanSetting.RENDERER_USE_SPEED_LIMIT.key) |
157 | add(ShortSetting.RENDERER_SPEED_LIMIT.key) | 159 | add(ShortSetting.RENDERER_SPEED_LIMIT.key) |
158 | add(BooleanSetting.USE_DOCKED_MODE.key) | 160 | add(BooleanSetting.USE_DOCKED_MODE.key) |
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt new file mode 100755 index 000000000..a4fd36f62 --- /dev/null +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/StringInputViewHolder.kt | |||
@@ -0,0 +1,45 @@ | |||
1 | // SPDX-FileCopyrightText: 2024 yuzu Emulator Project | ||
2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
3 | |||
4 | package org.yuzu.yuzu_emu.features.settings.ui.viewholder | ||
5 | |||
6 | import android.view.View | ||
7 | import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding | ||
8 | import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem | ||
9 | import org.yuzu.yuzu_emu.features.settings.model.view.StringInputSetting | ||
10 | import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter | ||
11 | import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible | ||
12 | |||
13 | class StringInputViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) : | ||
14 | SettingViewHolder(binding.root, adapter) { | ||
15 | private lateinit var setting: StringInputSetting | ||
16 | |||
17 | override fun bind(item: SettingsItem) { | ||
18 | setting = item as StringInputSetting | ||
19 | binding.textSettingName.text = setting.title | ||
20 | binding.textSettingDescription.setVisible(setting.description.isNotEmpty()) | ||
21 | binding.textSettingDescription.text = setting.description | ||
22 | binding.textSettingValue.setVisible(true) | ||
23 | binding.textSettingValue.text = setting.getSelectedValue() | ||
24 | |||
25 | binding.buttonClear.setVisible(setting.clearable) | ||
26 | binding.buttonClear.setOnClickListener { | ||
27 | adapter.onClearClick(setting, bindingAdapterPosition) | ||
28 | } | ||
29 | |||
30 | setStyle(setting.isEditable, binding) | ||
31 | } | ||
32 | |||
33 | override fun onClick(clicked: View) { | ||
34 | if (setting.isEditable) { | ||
35 | adapter.onStringInputClick(setting, bindingAdapterPosition) | ||
36 | } | ||
37 | } | ||
38 | |||
39 | override fun onLongClick(clicked: View): Boolean { | ||
40 | if (setting.isEditable) { | ||
41 | return adapter.onLongClick(setting, bindingAdapterPosition) | ||
42 | } | ||
43 | return false | ||
44 | } | ||
45 | } | ||
diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 6a631f664..f7f19cdad 100755 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml | |||
@@ -209,6 +209,7 @@ | |||
209 | <string name="value_with_units">%1$s%2$s</string> | 209 | <string name="value_with_units">%1$s%2$s</string> |
210 | 210 | ||
211 | <!-- System settings strings --> | 211 | <!-- System settings strings --> |
212 | <string name="device_name">Device name</string> | ||
212 | <string name="use_docked_mode">Docked Mode</string> | 213 | <string name="use_docked_mode">Docked Mode</string> |
213 | <string name="use_docked_mode_description">Increases resolution, decreasing performance. Handheld Mode is used when disabled, lowering resolution and increasing performance.</string> | 214 | <string name="use_docked_mode_description">Increases resolution, decreasing performance. Handheld Mode is used when disabled, lowering resolution and increasing performance.</string> |
214 | <string name="emulated_region">Emulated region</string> | 215 | <string name="emulated_region">Emulated region</string> |
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp index f537fb203..e71c58aa9 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp | |||
@@ -13,7 +13,6 @@ | |||
13 | #include "core/hle/service/nvdrv/nvdrv.h" | 13 | #include "core/hle/service/nvdrv/nvdrv.h" |
14 | #include "core/memory.h" | 14 | #include "core/memory.h" |
15 | #include "video_core/control/channel_state.h" | 15 | #include "video_core/control/channel_state.h" |
16 | #include "video_core/control/scheduler.h" | ||
17 | #include "video_core/engines/puller.h" | 16 | #include "video_core/engines/puller.h" |
18 | #include "video_core/gpu.h" | 17 | #include "video_core/gpu.h" |
19 | #include "video_core/host1x/host1x.h" | 18 | #include "video_core/host1x/host1x.h" |
@@ -34,7 +33,6 @@ nvhost_gpu::nvhost_gpu(Core::System& system_, EventInterface& events_interface_, | |||
34 | syncpoint_manager{core_.GetSyncpointManager()}, nvmap{core.GetNvMapFile()}, | 33 | syncpoint_manager{core_.GetSyncpointManager()}, nvmap{core.GetNvMapFile()}, |
35 | channel_state{system.GPU().AllocateChannel()} { | 34 | channel_state{system.GPU().AllocateChannel()} { |
36 | channel_syncpoint = syncpoint_manager.AllocateSyncpoint(false); | 35 | channel_syncpoint = syncpoint_manager.AllocateSyncpoint(false); |
37 | channel_state->syncpoint_id = channel_syncpoint; | ||
38 | sm_exception_breakpoint_int_report_event = | 36 | sm_exception_breakpoint_int_report_event = |
39 | events_interface.CreateEvent("GpuChannelSMExceptionBreakpointInt"); | 37 | events_interface.CreateEvent("GpuChannelSMExceptionBreakpointInt"); |
40 | sm_exception_breakpoint_pause_report_event = | 38 | sm_exception_breakpoint_pause_report_event = |
@@ -159,9 +157,6 @@ NvResult nvhost_gpu::SetErrorNotifier(IoctlSetErrorNotifier& params) { | |||
159 | 157 | ||
160 | NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) { | 158 | NvResult nvhost_gpu::SetChannelPriority(IoctlChannelSetPriority& params) { |
161 | channel_priority = params.priority; | 159 | channel_priority = params.priority; |
162 | if (channel_state->initialized) { | ||
163 | system.GPU().Scheduler().ChangePriority(channel_state->bind_id, channel_priority); | ||
164 | } | ||
165 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); | 160 | LOG_DEBUG(Service_NVDRV, "(STUBBED) called, priority={:X}", channel_priority); |
166 | return NvResult::Success; | 161 | return NvResult::Success; |
167 | } | 162 | } |
@@ -319,7 +314,6 @@ NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) { | |||
319 | NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) { | 314 | NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) { |
320 | LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); | 315 | LOG_INFO(Service_NVDRV, "called, timeout=0x{:X}", params.timeout); |
321 | 316 | ||
322 | channel_state->timeout = params.timeout; | ||
323 | return NvResult::Success; | 317 | return NvResult::Success; |
324 | } | 318 | } |
325 | 319 | ||
@@ -327,7 +321,6 @@ NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) { | |||
327 | LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); | 321 | LOG_INFO(Service_NVDRV, "called, timeslice=0x{:X}", params.timeslice); |
328 | 322 | ||
329 | channel_timeslice = params.timeslice; | 323 | channel_timeslice = params.timeslice; |
330 | channel_state->timeslice = params.timeslice; | ||
331 | 324 | ||
332 | return NvResult::Success; | 325 | return NvResult::Success; |
333 | } | 326 | } |
diff --git a/src/core/hle/service/vi/shared_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp index 3c0507d30..12cba16fa 100755 --- a/src/core/hle/service/vi/shared_buffer_manager.cpp +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp | |||
@@ -285,7 +285,7 @@ void SharedBufferManager::DestroySession(Kernel::KProcess* owner_process) { | |||
285 | auto& session = it->second; | 285 | auto& session = it->second; |
286 | 286 | ||
287 | // Destroy the layer. | 287 | // Destroy the layer. |
288 | R_ASSERT(m_container.DestroyStrayLayer(session.layer_id)); | 288 | m_container.DestroyStrayLayer(session.layer_id); |
289 | 289 | ||
290 | // Close nvmap handle. | 290 | // Close nvmap handle. |
291 | FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); | 291 | FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index b8ecffb8e..476418aa3 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp | |||
@@ -261,7 +261,9 @@ void DefineEntryPoint(const IR::Program& program, EmitContext& ctx, Id main) { | |||
261 | case Stage::Geometry: | 261 | case Stage::Geometry: |
262 | execution_model = spv::ExecutionModel::Geometry; | 262 | execution_model = spv::ExecutionModel::Geometry; |
263 | ctx.AddCapability(spv::Capability::Geometry); | 263 | ctx.AddCapability(spv::Capability::Geometry); |
264 | ctx.AddCapability(spv::Capability::GeometryStreams); | 264 | if (ctx.profile.support_geometry_streams) { |
265 | ctx.AddCapability(spv::Capability::GeometryStreams); | ||
266 | } | ||
265 | switch (ctx.runtime_info.input_topology) { | 267 | switch (ctx.runtime_info.input_topology) { |
266 | case InputTopology::Points: | 268 | case InputTopology::Points: |
267 | ctx.AddExecutionMode(main, spv::ExecutionMode::InputPoints); | 269 | ctx.AddExecutionMode(main, spv::ExecutionMode::InputPoints); |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp index 67bf5dc9f..f4c1ebba6 100755 --- a/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_special.cpp | |||
@@ -129,7 +129,9 @@ void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { | |||
129 | if (ctx.runtime_info.convert_depth_mode && !ctx.profile.support_native_ndc) { | 129 | if (ctx.runtime_info.convert_depth_mode && !ctx.profile.support_native_ndc) { |
130 | ConvertDepthMode(ctx); | 130 | ConvertDepthMode(ctx); |
131 | } | 131 | } |
132 | if (stream.IsImmediate()) { | 132 | if (!ctx.profile.support_geometry_streams) { |
133 | throw NotImplementedException("Geometry streams"); | ||
134 | } else if (stream.IsImmediate()) { | ||
133 | ctx.OpEmitStreamVertex(ctx.Def(stream)); | 135 | ctx.OpEmitStreamVertex(ctx.Def(stream)); |
134 | } else { | 136 | } else { |
135 | LOG_WARNING(Shader_SPIRV, "Stream is not immediate"); | 137 | LOG_WARNING(Shader_SPIRV, "Stream is not immediate"); |
@@ -140,7 +142,9 @@ void EmitEmitVertex(EmitContext& ctx, const IR::Value& stream) { | |||
140 | } | 142 | } |
141 | 143 | ||
142 | void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { | 144 | void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) { |
143 | if (stream.IsImmediate()) { | 145 | if (!ctx.profile.support_geometry_streams) { |
146 | throw NotImplementedException("Geometry streams"); | ||
147 | } else if (stream.IsImmediate()) { | ||
144 | ctx.OpEndStreamPrimitive(ctx.Def(stream)); | 148 | ctx.OpEndStreamPrimitive(ctx.Def(stream)); |
145 | } else { | 149 | } else { |
146 | LOG_WARNING(Shader_SPIRV, "Stream is not immediate"); | 150 | LOG_WARNING(Shader_SPIRV, "Stream is not immediate"); |
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 70ea46bb2..19089775d 100755 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h | |||
@@ -44,6 +44,7 @@ struct Profile { | |||
44 | bool support_gl_derivative_control{}; | 44 | bool support_gl_derivative_control{}; |
45 | bool support_scaled_attributes{}; | 45 | bool support_scaled_attributes{}; |
46 | bool support_multi_viewport{}; | 46 | bool support_multi_viewport{}; |
47 | bool support_geometry_streams{}; | ||
47 | 48 | ||
48 | bool warp_size_potentially_larger_than_guest{}; | 49 | bool warp_size_potentially_larger_than_guest{}; |
49 | 50 | ||
diff --git a/src/video_core/control/channel_state.h b/src/video_core/control/channel_state.h index 9f9b4ff75..ceaa92647 100755 --- a/src/video_core/control/channel_state.h +++ b/src/video_core/control/channel_state.h | |||
@@ -45,12 +45,6 @@ struct ChannelState { | |||
45 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); | 45 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); |
46 | 46 | ||
47 | s32 bind_id = -1; | 47 | s32 bind_id = -1; |
48 | /// Scheduling info | ||
49 | u32 syncpoint_id = 0xFFFF; | ||
50 | u32 priority = 0; | ||
51 | u32 timeslice = 0; | ||
52 | u32 timeout = 0; | ||
53 | |||
54 | /// 3D engine | 48 | /// 3D engine |
55 | std::unique_ptr<Engines::Maxwell3D> maxwell_3d; | 49 | std::unique_ptr<Engines::Maxwell3D> maxwell_3d; |
56 | /// 2D engine | 50 | /// 2D engine |
diff --git a/src/video_core/control/scheduler.cpp b/src/video_core/control/scheduler.cpp index f57efd189..31e3b1235 100755 --- a/src/video_core/control/scheduler.cpp +++ b/src/video_core/control/scheduler.cpp | |||
@@ -1,245 +1,32 @@ | |||
1 | // SPDX-FileCopyrightText: 2021 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: 2021 yuzu Emulator Project |
2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
3 | 3 | ||
4 | #include <atomic> | ||
5 | #include <deque> | ||
6 | #include <map> | ||
7 | #include <memory> | 4 | #include <memory> |
8 | #include <mutex> | ||
9 | #include <unordered_map> | ||
10 | #include <utility> | ||
11 | 5 | ||
12 | #include "common/assert.h" | 6 | #include "common/assert.h" |
13 | #include "common/fiber.h" | 7 | #include "video_core/control/channel_state.h" |
14 | #include "video_core/control/scheduler.h" | 8 | #include "video_core/control/scheduler.h" |
15 | #include "video_core/dma_pusher.h" | ||
16 | #include "video_core/gpu.h" | 9 | #include "video_core/gpu.h" |
17 | 10 | ||
18 | namespace Tegra::Control { | 11 | namespace Tegra::Control { |
19 | 12 | Scheduler::Scheduler(GPU& gpu_) : gpu{gpu_} {} | |
20 | struct GPFifoContext { | ||
21 | bool is_active; | ||
22 | bool is_running; | ||
23 | std::shared_ptr<Common::Fiber> context; | ||
24 | std::deque<CommandList> pending_work; | ||
25 | std::mutex guard; | ||
26 | s32 bind_id; | ||
27 | std::shared_ptr<ChannelState> info; | ||
28 | size_t yield_count; | ||
29 | size_t scheduled_count; | ||
30 | }; | ||
31 | |||
32 | struct Scheduler::SchedulerImpl { | ||
33 | // Fifos | ||
34 | std::map<u32, std::list<size_t>, std::greater<u32>> schedule_priority_queue; | ||
35 | std::unordered_map<s32, size_t> channel_gpfifo_ids; | ||
36 | std::deque<GPFifoContext> gpfifos; | ||
37 | std::deque<size_t> free_fifos; | ||
38 | |||
39 | // Scheduling | ||
40 | std::mutex scheduling_guard; | ||
41 | std::shared_ptr<Common::Fiber> master_control; | ||
42 | bool must_reschedule{}; | ||
43 | GPFifoContext* current_fifo{}; | ||
44 | }; | ||
45 | |||
46 | Scheduler::Scheduler(GPU& gpu_) : gpu{gpu_} { | ||
47 | impl = std::make_unique<SchedulerImpl>(); | ||
48 | } | ||
49 | 13 | ||
50 | Scheduler::~Scheduler() = default; | 14 | Scheduler::~Scheduler() = default; |
51 | 15 | ||
52 | void Scheduler::Init() { | ||
53 | impl->master_control = Common::Fiber::ThreadToFiber(); | ||
54 | } | ||
55 | |||
56 | void Scheduler::Resume() { | ||
57 | while (UpdateHighestPriorityChannel()) { | ||
58 | impl->current_fifo->scheduled_count++; | ||
59 | Common::Fiber::YieldTo(impl->master_control, *impl->current_fifo->context); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | bool Scheduler::UpdateHighestPriorityChannel() { | ||
64 | std::scoped_lock lk(impl->scheduling_guard); | ||
65 | |||
66 | // Clear needs to schedule state. | ||
67 | impl->must_reschedule = false; | ||
68 | |||
69 | // By default, we don't have a channel to schedule. | ||
70 | impl->current_fifo = nullptr; | ||
71 | |||
72 | // Check each level to see if we can schedule. | ||
73 | for (auto& level : impl->schedule_priority_queue) { | ||
74 | if (ScheduleLevel(level.second)) { | ||
75 | return true; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | // Nothing to schedule. | ||
80 | return false; | ||
81 | } | ||
82 | |||
83 | bool Scheduler::ScheduleLevel(std::list<size_t>& queue) { | ||
84 | bool found_anything = false; | ||
85 | size_t min_schedule_count = std::numeric_limits<size_t>::max(); | ||
86 | for (auto id : queue) { | ||
87 | auto& fifo = impl->gpfifos[id]; | ||
88 | std::scoped_lock lk(fifo.guard); | ||
89 | |||
90 | // With no pending work and nothing running, this channel can't be scheduled. | ||
91 | if (fifo.pending_work.empty() && !fifo.is_running) { | ||
92 | continue; | ||
93 | } | ||
94 | // Prioritize channels at current priority which have been run the least. | ||
95 | if (fifo.scheduled_count > min_schedule_count) { | ||
96 | continue; | ||
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; | ||
109 | } | ||
110 | return found_anything; | ||
111 | } | ||
112 | |||
113 | void Scheduler::ChangePriority(s32 channel_id, u32 new_priority) { | ||
114 | std::scoped_lock lk(impl->scheduling_guard); | ||
115 | // Ensure we are tracking this channel. | ||
116 | auto fifo_it = impl->channel_gpfifo_ids.find(channel_id); | ||
117 | if (fifo_it == impl->channel_gpfifo_ids.end()) { | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | // Get the fifo and update its priority. | ||
122 | const size_t fifo_id = fifo_it->second; | ||
123 | auto& fifo = impl->gpfifos[fifo_id]; | ||
124 | const auto old_priority = std::exchange(fifo.info->priority, new_priority); | ||
125 | |||
126 | // Create the new level if needed. | ||
127 | impl->schedule_priority_queue.try_emplace(new_priority); | ||
128 | |||
129 | // Remove the old level and add to the new level. | ||
130 | impl->schedule_priority_queue[new_priority].push_back(fifo_id); | ||
131 | impl->schedule_priority_queue[old_priority].remove_if( | ||
132 | [fifo_id](size_t id) { return id == fifo_id; }); | ||
133 | } | ||
134 | |||
135 | void Scheduler::Yield() { | ||
136 | ASSERT(impl->current_fifo != nullptr); | ||
137 | |||
138 | // Set yield count higher | ||
139 | impl->current_fifo->yield_count = impl->current_fifo->scheduled_count + 1; | ||
140 | Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); | ||
141 | gpu.BindChannel(impl->current_fifo->bind_id); | ||
142 | } | ||
143 | |||
144 | void Scheduler::CheckStatus() { | ||
145 | { | ||
146 | std::unique_lock lk(impl->scheduling_guard); | ||
147 | // If no reschedule is needed, don't transfer control | ||
148 | if (!impl->must_reschedule) { | ||
149 | return; | ||
150 | } | ||
151 | } | ||
152 | // Transfer control to the scheduler | ||
153 | Common::Fiber::YieldTo(impl->current_fifo->context, *impl->master_control); | ||
154 | gpu.BindChannel(impl->current_fifo->bind_id); | ||
155 | } | ||
156 | |||
157 | void Scheduler::Push(s32 channel, CommandList&& entries) { | 16 | void Scheduler::Push(s32 channel, CommandList&& entries) { |
158 | std::scoped_lock lk(impl->scheduling_guard); | 17 | std::unique_lock lk(scheduling_guard); |
159 | // Get and ensure we have this channel. | 18 | auto it = channels.find(channel); |
160 | auto it = impl->channel_gpfifo_ids.find(channel); | 19 | ASSERT(it != channels.end()); |
161 | ASSERT(it != impl->channel_gpfifo_ids.end()); | 20 | auto channel_state = it->second; |
162 | auto gpfifo_id = it->second; | 21 | gpu.BindChannel(channel_state->bind_id); |
163 | auto& fifo = impl->gpfifos[gpfifo_id]; | 22 | channel_state->dma_pusher->Push(std::move(entries)); |
164 | // Add the new new work to the channel. | 23 | channel_state->dma_pusher->DispatchCalls(); |
165 | { | ||
166 | std::scoped_lock lk2(fifo.guard); | ||
167 | fifo.pending_work.emplace_back(std::move(entries)); | ||
168 | } | ||
169 | |||
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; | ||
179 | } | ||
180 | // Mark scheduler update as required. | ||
181 | impl->must_reschedule = true; | ||
182 | } | ||
183 | |||
184 | void Scheduler::ChannelLoop(size_t gpfifo_id, s32 channel_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); | ||
204 | while (true) { | ||
205 | while (SendToPuller()) { | ||
206 | // Execute. | ||
207 | channel_state->dma_pusher->DispatchCalls(); | ||
208 | // Reschedule. | ||
209 | CheckStatus(); | ||
210 | } | ||
211 | // Return to host execution when all work is completed. | ||
212 | Common::Fiber::YieldTo(fifo.context, *impl->master_control); | ||
213 | // Inform the GPU about the current channel. | ||
214 | gpu.BindChannel(channel_id); | ||
215 | } | ||
216 | } | 24 | } |
217 | 25 | ||
218 | void Scheduler::DeclareChannel(std::shared_ptr<ChannelState> new_channel) { | 26 | void Scheduler::DeclareChannel(std::shared_ptr<ChannelState> new_channel) { |
219 | s32 channel = new_channel->bind_id; | 27 | s32 channel = new_channel->bind_id; |
220 | std::unique_lock lk(impl->scheduling_guard); | 28 | std::unique_lock lk(scheduling_guard); |
221 | 29 | channels.emplace(channel, new_channel); | |
222 | size_t new_fifo_id; | ||
223 | if (!impl->free_fifos.empty()) { | ||
224 | new_fifo_id = impl->free_fifos.front(); | ||
225 | impl->free_fifos.pop_front(); | ||
226 | } else { | ||
227 | new_fifo_id = impl->gpfifos.size(); | ||
228 | impl->gpfifos.emplace_back(); | ||
229 | } | ||
230 | auto& new_fifo = impl->gpfifos[new_fifo_id]; | ||
231 | impl->channel_gpfifo_ids[channel] = new_fifo_id; | ||
232 | new_fifo.is_active = true; | ||
233 | new_fifo.bind_id = channel; | ||
234 | new_fifo.pending_work.clear(); | ||
235 | new_fifo.info = new_channel; | ||
236 | new_fifo.scheduled_count = 0; | ||
237 | new_fifo.yield_count = 0; | ||
238 | new_fifo.is_running = false; | ||
239 | impl->schedule_priority_queue.try_emplace(new_channel->priority); | ||
240 | impl->schedule_priority_queue[new_channel->priority].push_back(new_fifo_id); | ||
241 | std::function<void()> callback = std::bind(&Scheduler::ChannelLoop, this, new_fifo_id, channel); | ||
242 | new_fifo.context = std::make_shared<Common::Fiber>(std::move(callback)); | ||
243 | } | 30 | } |
244 | 31 | ||
245 | } // namespace Tegra::Control | 32 | } // namespace Tegra::Control |
diff --git a/src/video_core/control/scheduler.h b/src/video_core/control/scheduler.h index 9b5620499..eab52e536 100755 --- a/src/video_core/control/scheduler.h +++ b/src/video_core/control/scheduler.h | |||
@@ -3,11 +3,10 @@ | |||
3 | 3 | ||
4 | #pragma once | 4 | #pragma once |
5 | 5 | ||
6 | #include <list> | ||
7 | #include <memory> | 6 | #include <memory> |
7 | #include <mutex> | ||
8 | #include <unordered_map> | ||
8 | 9 | ||
9 | #include "common/common_types.h" | ||
10 | #include "video_core/control/channel_state.h" | ||
11 | #include "video_core/dma_pusher.h" | 10 | #include "video_core/dma_pusher.h" |
12 | 11 | ||
13 | namespace Tegra { | 12 | namespace Tegra { |
@@ -23,27 +22,13 @@ public: | |||
23 | explicit Scheduler(GPU& gpu_); | 22 | explicit Scheduler(GPU& gpu_); |
24 | ~Scheduler(); | 23 | ~Scheduler(); |
25 | 24 | ||
26 | void Init(); | ||
27 | |||
28 | void Resume(); | ||
29 | |||
30 | void Yield(); | ||
31 | |||
32 | void Push(s32 channel, CommandList&& entries); | 25 | void Push(s32 channel, CommandList&& entries); |
33 | 26 | ||
34 | void DeclareChannel(std::shared_ptr<ChannelState> new_channel); | 27 | void DeclareChannel(std::shared_ptr<ChannelState> new_channel); |
35 | 28 | ||
36 | void ChangePriority(s32 channel_id, u32 new_priority); | ||
37 | |||
38 | private: | 29 | private: |
39 | void ChannelLoop(size_t gpfifo_id, s32 channel_id); | 30 | std::unordered_map<s32, std::shared_ptr<ChannelState>> channels; |
40 | bool ScheduleLevel(std::list<size_t>& queue); | 31 | std::mutex scheduling_guard; |
41 | void CheckStatus(); | ||
42 | bool UpdateHighestPriorityChannel(); | ||
43 | |||
44 | struct SchedulerImpl; | ||
45 | std::unique_ptr<SchedulerImpl> impl; | ||
46 | |||
47 | GPU& gpu; | 32 | GPU& gpu; |
48 | }; | 33 | }; |
49 | 34 | ||
diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp index c39cada43..79d84d662 100755 --- a/src/video_core/engines/puller.cpp +++ b/src/video_core/engines/puller.cpp | |||
@@ -6,7 +6,6 @@ | |||
6 | #include "common/settings.h" | 6 | #include "common/settings.h" |
7 | #include "core/core.h" | 7 | #include "core/core.h" |
8 | #include "video_core/control/channel_state.h" | 8 | #include "video_core/control/channel_state.h" |
9 | #include "video_core/control/scheduler.h" | ||
10 | #include "video_core/dma_pusher.h" | 9 | #include "video_core/dma_pusher.h" |
11 | #include "video_core/engines/fermi_2d.h" | 10 | #include "video_core/engines/fermi_2d.h" |
12 | #include "video_core/engines/kepler_compute.h" | 11 | #include "video_core/engines/kepler_compute.h" |
@@ -15,8 +14,6 @@ | |||
15 | #include "video_core/engines/maxwell_dma.h" | 14 | #include "video_core/engines/maxwell_dma.h" |
16 | #include "video_core/engines/puller.h" | 15 | #include "video_core/engines/puller.h" |
17 | #include "video_core/gpu.h" | 16 | #include "video_core/gpu.h" |
18 | #include "video_core/host1x/host1x.h" | ||
19 | #include "video_core/host1x/syncpoint_manager.h" | ||
20 | #include "video_core/memory_manager.h" | 17 | #include "video_core/memory_manager.h" |
21 | #include "video_core/rasterizer_interface.h" | 18 | #include "video_core/rasterizer_interface.h" |
22 | 19 | ||
@@ -63,14 +60,11 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) { | |||
63 | } | 60 | } |
64 | 61 | ||
65 | void Puller::ProcessFenceActionMethod() { | 62 | void Puller::ProcessFenceActionMethod() { |
66 | auto& syncpoint_manager = gpu.Host1x().GetSyncpointManager(); | ||
67 | switch (regs.fence_action.op) { | 63 | switch (regs.fence_action.op) { |
68 | case Puller::FenceOperation::Acquire: | 64 | case Puller::FenceOperation::Acquire: |
69 | while (regs.fence_value > | 65 | // UNIMPLEMENTED_MSG("Channel Scheduling pending."); |
70 | syncpoint_manager.GetGuestSyncpointValue(regs.fence_action.syncpoint_id)) { | 66 | // WaitFence(regs.fence_action.syncpoint_id, regs.fence_value); |
71 | rasterizer->ReleaseFences(); | 67 | rasterizer->ReleaseFences(); |
72 | gpu.Scheduler().Yield(); | ||
73 | } | ||
74 | break; | 68 | break; |
75 | case Puller::FenceOperation::Increment: | 69 | case Puller::FenceOperation::Increment: |
76 | rasterizer->SignalSyncPoint(regs.fence_action.syncpoint_id); | 70 | rasterizer->SignalSyncPoint(regs.fence_action.syncpoint_id); |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index f45f797b3..59356015b 100755 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
@@ -387,14 +387,6 @@ std::shared_ptr<Control::ChannelState> GPU::AllocateChannel() { | |||
387 | return impl->AllocateChannel(); | 387 | return impl->AllocateChannel(); |
388 | } | 388 | } |
389 | 389 | ||
390 | Tegra::Control::Scheduler& GPU::Scheduler() { | ||
391 | return *impl->scheduler; | ||
392 | } | ||
393 | |||
394 | const Tegra::Control::Scheduler& GPU::Scheduler() const { | ||
395 | return *impl->scheduler; | ||
396 | } | ||
397 | |||
398 | void GPU::InitChannel(Control::ChannelState& to_init) { | 390 | void GPU::InitChannel(Control::ChannelState& to_init) { |
399 | impl->InitChannel(to_init); | 391 | impl->InitChannel(to_init); |
400 | } | 392 | } |
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 154466f23..25c75a109 100755 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h | |||
@@ -124,8 +124,7 @@ class KeplerCompute; | |||
124 | 124 | ||
125 | namespace Control { | 125 | namespace Control { |
126 | struct ChannelState; | 126 | struct ChannelState; |
127 | class Scheduler; | 127 | } |
128 | } // namespace Control | ||
129 | 128 | ||
130 | namespace Host1x { | 129 | namespace Host1x { |
131 | class Host1x; | 130 | class Host1x; |
@@ -205,12 +204,6 @@ public: | |||
205 | /// Returns a const reference to the shader notifier. | 204 | /// Returns a const reference to the shader notifier. |
206 | [[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const; | 205 | [[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const; |
207 | 206 | ||
208 | /// Returns GPU Channel Scheduler. | ||
209 | [[nodiscard]] Tegra::Control::Scheduler& Scheduler(); | ||
210 | |||
211 | /// Returns GPU Channel Scheduler. | ||
212 | [[nodiscard]] const Tegra::Control::Scheduler& Scheduler() const; | ||
213 | |||
214 | [[nodiscard]] u64 GetTicks() const; | 207 | [[nodiscard]] u64 GetTicks() const; |
215 | 208 | ||
216 | [[nodiscard]] bool IsAsync() const; | 209 | [[nodiscard]] bool IsAsync() const; |
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 7decd2826..1b1b27768 100755 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp | |||
@@ -36,15 +36,13 @@ static void RunThread(std::stop_token stop_token, Core::System& system, | |||
36 | 36 | ||
37 | CommandDataContainer next; | 37 | CommandDataContainer next; |
38 | 38 | ||
39 | scheduler.Init(); | ||
40 | |||
41 | while (!stop_token.stop_requested()) { | 39 | while (!stop_token.stop_requested()) { |
42 | state.queue.PopWait(next, stop_token); | 40 | state.queue.PopWait(next, stop_token); |
43 | if (stop_token.stop_requested()) { | 41 | if (stop_token.stop_requested()) { |
44 | break; | 42 | break; |
45 | } | 43 | } |
46 | if (std::holds_alternative<SubmitListCommand>(next.data)) { | 44 | if (auto* submit_list = std::get_if<SubmitListCommand>(&next.data)) { |
47 | scheduler.Resume(); | 45 | scheduler.Push(submit_list->channel, std::move(submit_list->entries)); |
48 | } else if (std::holds_alternative<GPUTickCommand>(next.data)) { | 46 | } else if (std::holds_alternative<GPUTickCommand>(next.data)) { |
49 | system.GPU().TickWork(); | 47 | system.GPU().TickWork(); |
50 | } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) { | 48 | } else if (const auto* flush = std::get_if<FlushRegionCommand>(&next.data)) { |
@@ -71,16 +69,14 @@ ThreadManager::~ThreadManager() = default; | |||
71 | 69 | ||
72 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, | 70 | void ThreadManager::StartThread(VideoCore::RendererBase& renderer, |
73 | Core::Frontend::GraphicsContext& context, | 71 | Core::Frontend::GraphicsContext& context, |
74 | Tegra::Control::Scheduler& scheduler_) { | 72 | Tegra::Control::Scheduler& scheduler) { |
75 | rasterizer = renderer.ReadRasterizer(); | 73 | rasterizer = renderer.ReadRasterizer(); |
76 | scheduler = &scheduler_; | ||
77 | thread = std::jthread(RunThread, std::ref(system), std::ref(renderer), std::ref(context), | 74 | thread = std::jthread(RunThread, std::ref(system), std::ref(renderer), std::ref(context), |
78 | std::ref(scheduler_), std::ref(state)); | 75 | std::ref(scheduler), std::ref(state)); |
79 | } | 76 | } |
80 | 77 | ||
81 | void ThreadManager::SubmitList(s32 channel, Tegra::CommandList&& entries) { | 78 | void ThreadManager::SubmitList(s32 channel, Tegra::CommandList&& entries) { |
82 | scheduler->Push(channel, std::move(entries)); | 79 | PushCommand(SubmitListCommand(channel, std::move(entries))); |
83 | PushCommand(SubmitListCommand()); | ||
84 | } | 80 | } |
85 | 81 | ||
86 | void ThreadManager::FlushRegion(DAddr addr, u64 size) { | 82 | void ThreadManager::FlushRegion(DAddr addr, u64 size) { |
diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index a4b01c42a..1a0de86b5 100755 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h | |||
@@ -36,7 +36,13 @@ class RendererBase; | |||
36 | namespace VideoCommon::GPUThread { | 36 | namespace VideoCommon::GPUThread { |
37 | 37 | ||
38 | /// Command to signal to the GPU thread that a command list is ready for processing | 38 | /// Command to signal to the GPU thread that a command list is ready for processing |
39 | struct SubmitListCommand final {}; | 39 | struct SubmitListCommand final { |
40 | explicit SubmitListCommand(s32 channel_, Tegra::CommandList&& entries_) | ||
41 | : channel{channel_}, entries{std::move(entries_)} {} | ||
42 | |||
43 | s32 channel; | ||
44 | Tegra::CommandList entries; | ||
45 | }; | ||
40 | 46 | ||
41 | /// Command to signal to the GPU thread to flush a region | 47 | /// Command to signal to the GPU thread to flush a region |
42 | struct FlushRegionCommand final { | 48 | struct FlushRegionCommand final { |
@@ -118,7 +124,6 @@ public: | |||
118 | private: | 124 | private: |
119 | /// Pushes a command to be executed by the GPU thread | 125 | /// Pushes a command to be executed by the GPU thread |
120 | u64 PushCommand(CommandData&& command_data, bool block = false); | 126 | u64 PushCommand(CommandData&& command_data, bool block = false); |
121 | Tegra::Control::Scheduler* scheduler; | ||
122 | 127 | ||
123 | Core::System& system; | 128 | Core::System& system; |
124 | const bool is_async; | 129 | const bool is_async; |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index e5e90c069..a391aaae5 100755 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
@@ -352,6 +352,7 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, | |||
352 | .support_native_ndc = device.IsExtDepthClipControlSupported(), | 352 | .support_native_ndc = device.IsExtDepthClipControlSupported(), |
353 | .support_scaled_attributes = !device.MustEmulateScaledFormats(), | 353 | .support_scaled_attributes = !device.MustEmulateScaledFormats(), |
354 | .support_multi_viewport = device.SupportsMultiViewport(), | 354 | .support_multi_viewport = device.SupportsMultiViewport(), |
355 | .support_geometry_streams = device.AreTransformFeedbackGeometryStreamsSupported(), | ||
355 | 356 | ||
356 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), | 357 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), |
357 | 358 | ||
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 88a653e94..f0cb2b2dc 100755 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
@@ -489,6 +489,11 @@ public: | |||
489 | return extensions.transform_feedback; | 489 | return extensions.transform_feedback; |
490 | } | 490 | } |
491 | 491 | ||
492 | /// Returns true if the device supports VK_EXT_transform_feedback properly. | ||
493 | bool AreTransformFeedbackGeometryStreamsSupported() const { | ||
494 | return features.transform_feedback.geometryStreams; | ||
495 | } | ||
496 | |||
492 | /// Returns true if the device supports VK_EXT_custom_border_color. | 497 | /// Returns true if the device supports VK_EXT_custom_border_color. |
493 | bool IsExtCustomBorderColorSupported() const { | 498 | bool IsExtCustomBorderColorSupported() const { |
494 | return extensions.custom_border_color; | 499 | return extensions.custom_border_color; |