mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-12 06:39:26 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| faa771646c | |||
| de59fa1ab4 | |||
| b79295c528 | |||
| c47bae4c4e | |||
| ca0eebcfe8 |
+89
@@ -0,0 +1,89 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.model.view
|
||||
|
||||
import androidx.annotation.ArrayRes
|
||||
import androidx.annotation.StringRes
|
||||
import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||
|
||||
class GpuUnswizzleSetting(
|
||||
@StringRes titleId: Int = 0,
|
||||
titleString: String = "",
|
||||
@StringRes descriptionId: Int = 0,
|
||||
descriptionString: String = "",
|
||||
@ArrayRes val textureSizeChoicesId: Int,
|
||||
@ArrayRes val textureSizeValuesId: Int,
|
||||
@ArrayRes val streamSizeChoicesId: Int,
|
||||
@ArrayRes val streamSizeValuesId: Int,
|
||||
@ArrayRes val chunkSizeChoicesId: Int,
|
||||
@ArrayRes val chunkSizeValuesId: Int
|
||||
) : SettingsItem(
|
||||
object : AbstractSetting {
|
||||
override val key: String = SettingsItem.GPU_UNSWIZZLE_COMBINED
|
||||
override val defaultValue: Any = false
|
||||
override val isSaveable = true
|
||||
override val isRuntimeModifiable = true
|
||||
override val isSwitchable = true
|
||||
override val pairedSettingKey: String = ""
|
||||
override var global: Boolean
|
||||
get() {
|
||||
return BooleanSetting.GPU_UNSWIZZLE_ENABLED.global &&
|
||||
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.global &&
|
||||
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.global &&
|
||||
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.global
|
||||
}
|
||||
set(value) {
|
||||
BooleanSetting.GPU_UNSWIZZLE_ENABLED.global = value
|
||||
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.global = value
|
||||
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.global = value
|
||||
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.global = value
|
||||
}
|
||||
override fun getValueAsString(needsGlobal: Boolean): String = "combined"
|
||||
override fun reset() {
|
||||
BooleanSetting.GPU_UNSWIZZLE_ENABLED.reset()
|
||||
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.reset()
|
||||
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.reset()
|
||||
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.reset()
|
||||
}
|
||||
},
|
||||
titleId,
|
||||
titleString,
|
||||
descriptionId,
|
||||
descriptionString
|
||||
) {
|
||||
override val type = SettingsItem.TYPE_GPU_UNSWIZZLE
|
||||
|
||||
// Check if GPU unswizzle is enabled via the dedicated boolean setting
|
||||
fun isEnabled(needsGlobal: Boolean = false): Boolean =
|
||||
BooleanSetting.GPU_UNSWIZZLE_ENABLED.getBoolean(needsGlobal)
|
||||
|
||||
fun setEnabled(value: Boolean) =
|
||||
BooleanSetting.GPU_UNSWIZZLE_ENABLED.setBoolean(value)
|
||||
|
||||
fun enable() = setEnabled(true)
|
||||
|
||||
fun disable() = setEnabled(false)
|
||||
|
||||
fun getTextureSize(needsGlobal: Boolean = false): Int =
|
||||
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.getInt(needsGlobal)
|
||||
|
||||
fun setTextureSize(value: Int) =
|
||||
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE.setInt(value)
|
||||
|
||||
fun getStreamSize(needsGlobal: Boolean = false): Int =
|
||||
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.getInt(needsGlobal)
|
||||
|
||||
fun setStreamSize(value: Int) =
|
||||
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE.setInt(value)
|
||||
|
||||
fun getChunkSize(needsGlobal: Boolean = false): Int =
|
||||
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.getInt(needsGlobal)
|
||||
|
||||
fun setChunkSize(value: Int) =
|
||||
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE.setInt(value)
|
||||
|
||||
fun reset() = setting.reset()
|
||||
}
|
||||
+21
-12
@@ -686,33 +686,42 @@ abstract class SettingsItem(
|
||||
)
|
||||
)
|
||||
put(
|
||||
SpinBoxSetting(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE,
|
||||
titleId = R.string.gpu_unswizzle_texture_size,
|
||||
descriptionId = R.string.gpu_unswizzle_texture_size_description,
|
||||
valueHint = R.string.gpu_unswizzle_texture_size,
|
||||
min = 1,
|
||||
max = 9
|
||||
choicesId = R.array.gpuTextureSizeSwizzleEntries,
|
||||
valuesId = R.array.gpuTextureSizeSwizzleValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SpinBoxSetting(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE,
|
||||
titleId = R.string.gpu_unswizzle_stream_size,
|
||||
descriptionId = R.string.gpu_unswizzle_stream_size_description,
|
||||
valueHint = R.string.gpu_unswizzle_stream_size,
|
||||
min = 1,
|
||||
max = 9
|
||||
choicesId = R.array.gpuSwizzleEntries,
|
||||
valuesId = R.array.gpuSwizzleValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
SpinBoxSetting(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE,
|
||||
titleId = R.string.gpu_unswizzle_chunk_size,
|
||||
descriptionId = R.string.gpu_unswizzle_chunk_size_description,
|
||||
valueHint = R.string.gpu_unswizzle_chunk_size,
|
||||
min = 1,
|
||||
max = 9
|
||||
choicesId = R.array.gpuSwizzleChunkEntries,
|
||||
valuesId = R.array.gpuSwizzleChunkValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
GpuUnswizzleSetting(
|
||||
titleId = R.string.gpu_unswizzle_settings,
|
||||
descriptionId = R.string.gpu_unswizzle_settings_description,
|
||||
textureSizeChoicesId = R.array.gpuTextureSizeSwizzleEntries,
|
||||
textureSizeValuesId = R.array.gpuTextureSizeSwizzleValues,
|
||||
streamSizeChoicesId = R.array.gpuSwizzleEntries,
|
||||
streamSizeValuesId = R.array.gpuSwizzleValues,
|
||||
chunkSizeChoicesId = R.array.gpuSwizzleChunkEntries,
|
||||
chunkSizeValuesId = R.array.gpuSwizzleChunkValues
|
||||
)
|
||||
)
|
||||
put(
|
||||
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.ui
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.DialogInterface
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.DialogGpuUnswizzleBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.GpuUnswizzleSetting
|
||||
|
||||
class GpuUnswizzleDialogFragment : DialogFragment() {
|
||||
private var position = 0
|
||||
private val settingsViewModel: SettingsViewModel by activityViewModels()
|
||||
private lateinit var binding: DialogGpuUnswizzleBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
position = requireArguments().getInt(POSITION)
|
||||
|
||||
if (settingsViewModel.clickedItem == null) dismiss()
|
||||
}
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
binding = DialogGpuUnswizzleBinding.inflate(LayoutInflater.from(requireContext()))
|
||||
val item = settingsViewModel.clickedItem as GpuUnswizzleSetting
|
||||
|
||||
// Setup texture size dropdown
|
||||
val textureSizeEntries = resources.getStringArray(item.textureSizeChoicesId)
|
||||
val textureSizeValues = resources.getIntArray(item.textureSizeValuesId)
|
||||
val textureSizeAdapter = ArrayAdapter(
|
||||
requireContext(),
|
||||
android.R.layout.simple_dropdown_item_1line,
|
||||
textureSizeEntries.toMutableList()
|
||||
)
|
||||
binding.dropdownTextureSize.setAdapter(textureSizeAdapter)
|
||||
|
||||
// Setup stream size dropdown
|
||||
val streamSizeEntries = resources.getStringArray(item.streamSizeChoicesId)
|
||||
val streamSizeValues = resources.getIntArray(item.streamSizeValuesId)
|
||||
val streamSizeAdapter = ArrayAdapter(
|
||||
requireContext(),
|
||||
android.R.layout.simple_dropdown_item_1line,
|
||||
streamSizeEntries.toMutableList()
|
||||
)
|
||||
binding.dropdownStreamSize.setAdapter(streamSizeAdapter)
|
||||
|
||||
// Setup chunk size dropdown
|
||||
val chunkSizeEntries = resources.getStringArray(item.chunkSizeChoicesId)
|
||||
val chunkSizeValues = resources.getIntArray(item.chunkSizeValuesId)
|
||||
val chunkSizeAdapter = ArrayAdapter(
|
||||
requireContext(),
|
||||
android.R.layout.simple_dropdown_item_1line,
|
||||
chunkSizeEntries.toMutableList()
|
||||
)
|
||||
binding.dropdownChunkSize.setAdapter(chunkSizeAdapter)
|
||||
|
||||
// Load current values
|
||||
val isEnabled = item.isEnabled()
|
||||
binding.switchEnable.isChecked = isEnabled
|
||||
|
||||
if (isEnabled) {
|
||||
val textureSizeIndex = textureSizeValues.indexOf(item.getTextureSize())
|
||||
if (textureSizeIndex >= 0) {
|
||||
binding.dropdownTextureSize.setText(textureSizeEntries[textureSizeIndex], false)
|
||||
}
|
||||
|
||||
val streamSizeIndex = streamSizeValues.indexOf(item.getStreamSize())
|
||||
if (streamSizeIndex >= 0) {
|
||||
binding.dropdownStreamSize.setText(streamSizeEntries[streamSizeIndex], false)
|
||||
}
|
||||
|
||||
val chunkSizeIndex = chunkSizeValues.indexOf(item.getChunkSize())
|
||||
if (chunkSizeIndex >= 0) {
|
||||
binding.dropdownChunkSize.setText(chunkSizeEntries[chunkSizeIndex], false)
|
||||
}
|
||||
} else {
|
||||
// Set default/recommended values when disabling
|
||||
binding.dropdownTextureSize.setText(textureSizeEntries[3], false)
|
||||
binding.dropdownStreamSize.setText(streamSizeEntries[3], false)
|
||||
binding.dropdownChunkSize.setText(chunkSizeEntries[3], false)
|
||||
}
|
||||
|
||||
// Clear adapter filters after setText to fix rotation bug
|
||||
textureSizeAdapter.filter.filter(null)
|
||||
streamSizeAdapter.filter.filter(null)
|
||||
chunkSizeAdapter.filter.filter(null)
|
||||
|
||||
// Enable/disable dropdowns based on switch state
|
||||
updateDropdownsState(isEnabled)
|
||||
binding.switchEnable.setOnCheckedChangeListener { _, checked ->
|
||||
updateDropdownsState(checked)
|
||||
}
|
||||
|
||||
val dialog = MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(item.title)
|
||||
.setView(binding.root)
|
||||
.create()
|
||||
|
||||
// Setup button listeners
|
||||
binding.btnDefault.setOnClickListener {
|
||||
// Reset to defaults
|
||||
item.reset()
|
||||
// Refresh values with adapters reset
|
||||
val textureSizeIndex = textureSizeValues.indexOf(item.getTextureSize())
|
||||
if (textureSizeIndex >= 0) {
|
||||
binding.dropdownTextureSize.setText(textureSizeEntries[textureSizeIndex], false)
|
||||
}
|
||||
val streamSizeIndex = streamSizeValues.indexOf(item.getStreamSize())
|
||||
if (streamSizeIndex >= 0) {
|
||||
binding.dropdownStreamSize.setText(streamSizeEntries[streamSizeIndex], false)
|
||||
}
|
||||
val chunkSizeIndex = chunkSizeValues.indexOf(item.getChunkSize())
|
||||
if (chunkSizeIndex >= 0) {
|
||||
binding.dropdownChunkSize.setText(chunkSizeEntries[chunkSizeIndex], false)
|
||||
}
|
||||
// Clear filters
|
||||
textureSizeAdapter.filter.filter(null)
|
||||
streamSizeAdapter.filter.filter(null)
|
||||
chunkSizeAdapter.filter.filter(null)
|
||||
|
||||
settingsViewModel.setAdapterItemChanged(position)
|
||||
settingsViewModel.setShouldReloadSettingsList(true)
|
||||
}
|
||||
|
||||
binding.btnCancel.setOnClickListener {
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
binding.btnOk.setOnClickListener {
|
||||
if (binding.switchEnable.isChecked) {
|
||||
item.enable()
|
||||
// Save the selected values
|
||||
val selectedTextureIndex = textureSizeEntries.indexOf(
|
||||
binding.dropdownTextureSize.text.toString()
|
||||
)
|
||||
if (selectedTextureIndex >= 0) {
|
||||
item.setTextureSize(textureSizeValues[selectedTextureIndex])
|
||||
}
|
||||
|
||||
val selectedStreamIndex = streamSizeEntries.indexOf(
|
||||
binding.dropdownStreamSize.text.toString()
|
||||
)
|
||||
if (selectedStreamIndex >= 0) {
|
||||
item.setStreamSize(streamSizeValues[selectedStreamIndex])
|
||||
}
|
||||
|
||||
val selectedChunkIndex = chunkSizeEntries.indexOf(
|
||||
binding.dropdownChunkSize.text.toString()
|
||||
)
|
||||
if (selectedChunkIndex >= 0) {
|
||||
item.setChunkSize(chunkSizeValues[selectedChunkIndex])
|
||||
}
|
||||
} else {
|
||||
// Disable GPU unswizzle
|
||||
item.disable()
|
||||
}
|
||||
|
||||
settingsViewModel.setAdapterItemChanged(position)
|
||||
settingsViewModel.setShouldReloadSettingsList(true)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
// Ensure filters are cleared after dialog is shown
|
||||
binding.root.post {
|
||||
textureSizeAdapter.filter.filter(null)
|
||||
streamSizeAdapter.filter.filter(null)
|
||||
chunkSizeAdapter.filter.filter(null)
|
||||
}
|
||||
|
||||
return dialog
|
||||
}
|
||||
|
||||
private fun updateDropdownsState(enabled: Boolean) {
|
||||
binding.layoutTextureSize.isEnabled = enabled
|
||||
binding.dropdownTextureSize.isEnabled = enabled
|
||||
binding.layoutStreamSize.isEnabled = enabled
|
||||
binding.dropdownStreamSize.isEnabled = enabled
|
||||
binding.layoutChunkSize.isEnabled = enabled
|
||||
binding.dropdownChunkSize.isEnabled = enabled
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TAG = "GpuUnswizzleDialogFragment"
|
||||
const val POSITION = "Position"
|
||||
|
||||
fun newInstance(
|
||||
settingsViewModel: SettingsViewModel,
|
||||
item: GpuUnswizzleSetting,
|
||||
position: Int
|
||||
): GpuUnswizzleDialogFragment {
|
||||
val dialog = GpuUnswizzleDialogFragment()
|
||||
val args = Bundle()
|
||||
args.putInt(POSITION, position)
|
||||
dialog.arguments = args
|
||||
settingsViewModel.clickedItem = item
|
||||
return dialog
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -102,6 +102,10 @@ class SettingsAdapter(
|
||||
PathViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_GPU_UNSWIZZLE -> {
|
||||
GpuUnswizzleViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||
}
|
||||
|
||||
else -> {
|
||||
HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)
|
||||
}
|
||||
@@ -475,6 +479,14 @@ class SettingsAdapter(
|
||||
settingsViewModel.setShouldShowPathResetDialog(true)
|
||||
}
|
||||
|
||||
fun onGpuUnswizzleClick(item: GpuUnswizzleSetting, position: Int) {
|
||||
GpuUnswizzleDialogFragment.newInstance(
|
||||
settingsViewModel,
|
||||
item,
|
||||
position
|
||||
).show(fragment.childFragmentManager, GpuUnswizzleDialogFragment.TAG)
|
||||
}
|
||||
|
||||
private class DiffCallback : DiffUtil.ItemCallback<SettingsItem>() {
|
||||
override fun areItemsTheSame(oldItem: SettingsItem, newItem: SettingsItem): Boolean {
|
||||
return oldItem.setting.key == newItem.setting.key
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.view.View
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.GpuUnswizzleSetting
|
||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||
|
||||
class GpuUnswizzleViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
||||
SettingViewHolder(binding.root, adapter) {
|
||||
private lateinit var setting: GpuUnswizzleSetting
|
||||
|
||||
override fun bind(item: SettingsItem) {
|
||||
setting = item as GpuUnswizzleSetting
|
||||
binding.textSettingName.text = setting.title
|
||||
binding.textSettingDescription.setVisible(item.description.isNotEmpty())
|
||||
binding.textSettingDescription.text = item.description
|
||||
|
||||
binding.textSettingValue.setVisible(true)
|
||||
val resMgr = binding.root.context.resources
|
||||
|
||||
if (setting.isEnabled()) {
|
||||
// Show a summary of current settings
|
||||
val textureSizeEntries = resMgr.getStringArray(setting.textureSizeChoicesId)
|
||||
val textureSizeValues = resMgr.getIntArray(setting.textureSizeValuesId)
|
||||
val textureSizeIndex = textureSizeValues.indexOf(setting.getTextureSize())
|
||||
val textureSizeLabel = if (textureSizeIndex >= 0) textureSizeEntries[textureSizeIndex] else "?"
|
||||
|
||||
val streamSizeEntries = resMgr.getStringArray(setting.streamSizeChoicesId)
|
||||
val streamSizeValues = resMgr.getIntArray(setting.streamSizeValuesId)
|
||||
val streamSizeIndex = streamSizeValues.indexOf(setting.getStreamSize())
|
||||
val streamSizeLabel = if (streamSizeIndex >= 0) streamSizeEntries[streamSizeIndex] else "?"
|
||||
|
||||
val chunkSizeEntries = resMgr.getStringArray(setting.chunkSizeChoicesId)
|
||||
val chunkSizeValues = resMgr.getIntArray(setting.chunkSizeValuesId)
|
||||
val chunkSizeIndex = chunkSizeValues.indexOf(setting.getChunkSize())
|
||||
val chunkSizeLabel = if (chunkSizeIndex >= 0) chunkSizeEntries[chunkSizeIndex] else "?"
|
||||
|
||||
binding.textSettingValue.text = "$textureSizeLabel ⋅ $streamSizeLabel ⋅ $chunkSizeLabel"
|
||||
} else {
|
||||
binding.textSettingValue.text = resMgr.getString(R.string.gpu_unswizzle_disabled)
|
||||
}
|
||||
|
||||
binding.buttonClear.setVisible(setting.clearable)
|
||||
binding.buttonClear.setOnClickListener {
|
||||
adapter.onClearClick(setting, bindingAdapterPosition)
|
||||
}
|
||||
|
||||
setStyle(setting.isEditable, binding)
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
if (!setting.isEditable) {
|
||||
return
|
||||
}
|
||||
|
||||
adapter.onGpuUnswizzleClick(setting, bindingAdapterPosition)
|
||||
}
|
||||
|
||||
override fun onLongClick(clicked: View): Boolean {
|
||||
if (setting.isEditable) {
|
||||
return adapter.onLongClick(setting, bindingAdapterPosition)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
@@ -516,7 +516,10 @@
|
||||
<string name="rescale_hack_description">يُمكّن هذا الخيار من التعامل مع عملية إعادة تحجيم الألعاب بطريقة تقليدية باستخدام مسار إعادة التحجيم السريع</string>
|
||||
<string name="renderer_asynchronous_shaders">استخدم تظليل غير متزامن</string>
|
||||
<string name="renderer_asynchronous_shaders_description">يقوم بتجميع التظليل بشكل غير متزامن. قد يقلل ذلك من التقطعات ولكنه قد يؤدي أيضًا إلى حدوث أخطاء.</string>
|
||||
<string name="gpu_unswizzle_settings">إعدادات إلغاء ترتيب بيانات وحدة معالجة الرسومات</string>
|
||||
<string name="gpu_unswizzle_settings_description">قم بضبط معلمات فكّ تشابك النسيج المستندة إلى وحدة معالجة الرسومات أو تعطيلها تمامًا. اضبط هذه الإعدادات لتحقيق التوازن بين الأداء وجودة تحميل النسيج.</string>
|
||||
<string name="gpu_unswizzle_enable">تفعيل إلغاء ترتيب بيانات وحدة معالجة الرسومات</string>
|
||||
<string name="gpu_unswizzle_disabled">تعطيل</string>
|
||||
<string name="gpu_unswizzle_texture_size">الحد الأقصى لحجم النسيج في وحدة معالجة الرسومات بعد إعادة ترتيب البيانات</string>
|
||||
<string name="gpu_unswizzle_texture_size_description">يُحدد هذا الخيار الحد الأقصى لحجم (ميغابايت) معالجة الصور باستخدام وحدة معالجة الرسومات. مع أن وحدة معالجة الرسومات أسرع في معالجة الصور المتوسطة والكبيرة، إلا أن وحدة المعالجة المركزية قد تكون أكثر كفاءة في معالجة الصور الصغيرة جدًا. اضبط هذا الخيار لتحقيق التوازن الأمثل بين سرعة معالجة الرسومات واستهلاك وحدة المعالجة المركزية.</string>
|
||||
<string name="gpu_unswizzle_stream_size">حجم تدفق إلغاء ترتيب بيانات وحدة معالجة الرسومات</string>
|
||||
@@ -954,10 +957,25 @@
|
||||
<string name="fast_gpu_high">مرتفع (512)</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">صغير جدًا (16 ميغابايت)</string>
|
||||
<string name="gpu_texturesizeswizzle_small">صغير (32 ميغابايت)</string>
|
||||
<string name="gpu_texturesizeswizzle_normal">قياسي (128 ميغابايت)</string>
|
||||
<string name="gpu_texturesizeswizzle_large">كبير (256 ميغابايت)</string>
|
||||
<string name="gpu_texturesizeswizzle_verylarge">كبير جدًا (512 ميغابايت)</string>
|
||||
|
||||
<!-- GPU swizzle streams -->
|
||||
<string name="gpu_swizzle_verylow">منخفض جدًا (4 ميغابايت)</string>
|
||||
<string name="gpu_swizzle_low">منخفض (8 ميغابايت)</string>
|
||||
<string name="gpu_swizzle_normal">قياسي (16 ميغابايت)</string>
|
||||
<string name="gpu_swizzle_medium">متوسط (32 ميغابايت)</string>
|
||||
<string name="gpu_swizzle_high">عالي (64 ميغابايت)</string>
|
||||
|
||||
<!-- GPU swizzle chunks -->
|
||||
<string name="gpu_swizzlechunk_verylow">منخفض جدًا (32)</string>
|
||||
<string name="gpu_swizzlechunk_low">منخفض (64)</string>
|
||||
<string name="gpu_swizzlechunk_normal">قياسي (128)</string>
|
||||
<string name="gpu_swizzlechunk_medium">متوسط (256)</string>
|
||||
<string name="gpu_swizzlechunk_high">عالي (512)</string>
|
||||
|
||||
<!-- Temperature Units -->
|
||||
<string name="temperature_celsius">مئوية</string>
|
||||
|
||||
@@ -890,10 +890,25 @@ Wirklich fortfahren?</string>
|
||||
<string name="fast_gpu_high">Hoch (512)</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">Sehr klein (16 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_small">Klein (32 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_normal">Normal (128 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_large">Groß (256 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_verylarge">Sehr groß (512 MB)</string>
|
||||
|
||||
<!-- GPU swizzle streams -->
|
||||
<string name="gpu_swizzle_verylow">Sehr niedrig (4 MB)</string>
|
||||
<string name="gpu_swizzle_low">Niedrig (8 MB)</string>
|
||||
<string name="gpu_swizzle_normal">Normal (16 MB)</string>
|
||||
<string name="gpu_swizzle_medium">Mittel (32 MB)</string>
|
||||
<string name="gpu_swizzle_high">Hoch (64 MB)</string>
|
||||
|
||||
<!-- GPU swizzle chunks -->
|
||||
<string name="gpu_swizzlechunk_verylow">Sehr niedrig (32)</string>
|
||||
<string name="gpu_swizzlechunk_low">Niedrig (64)</string>
|
||||
<string name="gpu_swizzlechunk_normal">Normal (128)</string>
|
||||
<string name="gpu_swizzlechunk_medium">Mittel (256)</string>
|
||||
<string name="gpu_swizzlechunk_high">Hoch (512)</string>
|
||||
|
||||
<!-- Temperature Units -->
|
||||
<string name="temperature_celsius">Celsius</string>
|
||||
|
||||
@@ -510,7 +510,10 @@
|
||||
<string name="rescale_hack_description">Permite el manejo de versiones anteriores para el paso de configuración de reescalado para juegos mediante el uso de una ruta de reescalado rápida.</string>
|
||||
<string name="renderer_asynchronous_shaders">Usar sombreadores asíncronos</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Compila los sombreadores de forma asíncrona. Esto puede reducir los tirones, pero también puede introducir errores gráficos.</string>
|
||||
<string name="gpu_unswizzle_settings">Ajustes de desentrelazado de la GPU</string>
|
||||
<string name="gpu_unswizzle_settings_description">Configura los parámetros de desentrelazado de texturas basadas en la GPU o desactívelos por completo. Modifique estos ajustes para equilibrar el rendimiento y la calidad de las texturas cargadas.</string>
|
||||
<string name="gpu_unswizzle_enable">Activar desentrelazado de la GPU</string>
|
||||
<string name="gpu_unswizzle_disabled">Desactivado</string>
|
||||
<string name="gpu_unswizzle_texture_size">Tamaño máximo de textura de desentrelazado de la GPU</string>
|
||||
<string name="gpu_unswizzle_texture_size_description">Establece el tamaño máximo (en MB) para el desentrelazado de texturas basada en GPU. Aunque la GPU es más rápida para texturas medianas y grandes, la CPU puede ser más eficiente para texturas muy pequeñas. Ajuste este valor para encontrar el equilibrio entre la aceleración de la GPU y la sobrecarga de la CPU.</string>
|
||||
<string name="gpu_unswizzle_stream_size">Tamaño del flujo de desentrelazado de la GPU</string>
|
||||
@@ -948,10 +951,25 @@
|
||||
<string name="fast_gpu_high">Alto (512)</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">Muy pequeño (16 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_small">Pequeño (32 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_normal">Normal (128 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_large">Grande (256 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_verylarge">Muy grande (512 MB)</string>
|
||||
|
||||
<!-- GPU swizzle streams -->
|
||||
<string name="gpu_swizzle_verylow">Muy bajo (4 MB)</string>
|
||||
<string name="gpu_swizzle_low">Bajo (8 MB)</string>
|
||||
<string name="gpu_swizzle_normal">Normal (16 MB)</string>
|
||||
<string name="gpu_swizzle_medium">Medio (32 MB)</string>
|
||||
<string name="gpu_swizzle_high">Alto (64 MB)</string>
|
||||
|
||||
<!-- GPU swizzle chunks -->
|
||||
<string name="gpu_swizzlechunk_verylow">Muy bajo (32)</string>
|
||||
<string name="gpu_swizzlechunk_low">Bajo (64)</string>
|
||||
<string name="gpu_swizzlechunk_normal">Normal (128)</string>
|
||||
<string name="gpu_swizzlechunk_medium">Medio (256)</string>
|
||||
<string name="gpu_swizzlechunk_high">Alto (512)</string>
|
||||
|
||||
<!-- Temperature Units -->
|
||||
<string name="temperature_celsius">Celsius</string>
|
||||
|
||||
@@ -509,7 +509,10 @@
|
||||
<string name="rescale_hack_description">Включает старый метод обработки этапа перенастройки масштабирования для игр за счёт использования быстрого алгоритма перемасштабирования.</string>
|
||||
<string name="renderer_asynchronous_shaders">Использовать асинхронные шейдеры</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Компилирует шейдеры асинхронно. Это может уменьшить подтормаживания, но также может вызвать графические артефакты.</string>
|
||||
<string name="gpu_unswizzle_settings">Настройки распаковки текстур (Unswizzle)</string>
|
||||
<string name="gpu_unswizzle_settings_description">Настройте параметры распаковки текстур на стороне ГПУ либо полностью отключите эту функцию. Изменение этих параметров позволяет найти баланс между производительностью и качеством загрузки текстур.</string>
|
||||
<string name="gpu_unswizzle_enable">Включить распаковку текстур (Unswizzle)</string>
|
||||
<string name="gpu_unswizzle_disabled">Отключено</string>
|
||||
<string name="gpu_unswizzle_texture_size">Макс. размер текстуры Unswizzle</string>
|
||||
<string name="gpu_unswizzle_texture_size_description">Задает максимальный размер (в МБ) текстур для преобразования формата (unswizzle) на ГПУ. Хотя ГПУ быстрее работает со средними и большими текстурами, ЦП может быть эффективнее для очень маленьких. Настройте это значение, чтобы найти баланс между ускорением на ГПУ и нагрузкой на ЦП.</string>
|
||||
<string name="gpu_unswizzle_stream_size">Размер потока Unswizzle</string>
|
||||
@@ -947,10 +950,25 @@
|
||||
<string name="fast_gpu_high">Высокое (512)</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">Очень малый (16 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_small">Малый (32 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_normal">Обычный (128 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_large">Большой (256 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_verylarge">Очень большой (512 МБ)</string>
|
||||
|
||||
<!-- GPU swizzle streams -->
|
||||
<string name="gpu_swizzle_verylow">Очень низкий (4 МБ)</string>
|
||||
<string name="gpu_swizzle_low">Низкий (8 МБ)</string>
|
||||
<string name="gpu_swizzle_normal">Обычный (16 МБ)</string>
|
||||
<string name="gpu_swizzle_medium">Средний (32 МБ)</string>
|
||||
<string name="gpu_swizzle_high">Высокий (64 МБ)</string>
|
||||
|
||||
<!-- GPU swizzle chunks -->
|
||||
<string name="gpu_swizzlechunk_verylow">Очень малый (32)</string>
|
||||
<string name="gpu_swizzlechunk_low">Малый (64)</string>
|
||||
<string name="gpu_swizzlechunk_normal">Обычный (128)</string>
|
||||
<string name="gpu_swizzlechunk_medium">Средний (256)</string>
|
||||
<string name="gpu_swizzlechunk_high">Большой (512)</string>
|
||||
|
||||
<!-- Temperature Units -->
|
||||
<string name="temperature_celsius">Цельсий</string>
|
||||
|
||||
@@ -512,7 +512,10 @@
|
||||
<string name="rescale_hack_description">Вмикає застарілу обробку масштабування для ігор, використовуючи швидкий шлях масштабування</string>
|
||||
<string name="renderer_asynchronous_shaders">Асинхронні шейдери</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Компілює шейдери асинхронно. Це може зменшити затримки, але також може спричинити графічні баги.</string>
|
||||
<string name="gpu_unswizzle_settings">Налаштування розпакування за допомогою ГП</string>
|
||||
<string name="gpu_unswizzle_settings_description">Налаштуйте розпакування текстур за допомогою ГП або повністю вимкнути його. Відкоригуйте ці налаштування, щоб урівноважити продуктивність і якість завантаження текстур.</string>
|
||||
<string name="gpu_unswizzle_enable">Увімкнути розпакування за допомогою ГП</string>
|
||||
<string name="gpu_unswizzle_disabled">Вимкнено</string>
|
||||
<string name="gpu_unswizzle_texture_size">Максимальний розмір текстур для розпакування ГП за допомогою ГП</string>
|
||||
<string name="gpu_unswizzle_texture_size_description">Встановлює максимальний розмір (МБ) для розпакування текстур за допомогою ГП. ГП швидше справляється з текстурами середніх і великих розмірів, а ЦП ефективніший для дуже маленьких. Налаштуйте, щоб збалансувати ГП-прискоренням і навантаженням на ЦП.</string>
|
||||
<string name="gpu_unswizzle_stream_size">Розмір потоку розпакування за допомогою ГП</string>
|
||||
@@ -950,10 +953,25 @@
|
||||
<string name="fast_gpu_high">Високо (512)</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">Дуже малий (16 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_small">Малий (32 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_normal">Нормальний (128 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_large">Великий (256 МБ)</string>
|
||||
<string name="gpu_texturesizeswizzle_verylarge">Дуже великий (512 МБ)</string>
|
||||
|
||||
<!-- GPU swizzle streams -->
|
||||
<string name="gpu_swizzle_verylow">Дуже низький (4 МБ)</string>
|
||||
<string name="gpu_swizzle_low">Низький (8 МБ)</string>
|
||||
<string name="gpu_swizzle_normal">Нормальний (16 МБ)</string>
|
||||
<string name="gpu_swizzle_medium">Середній (32 МБ)</string>
|
||||
<string name="gpu_swizzle_high">Високий (64 МБ)</string>
|
||||
|
||||
<!-- GPU swizzle chunks -->
|
||||
<string name="gpu_swizzlechunk_verylow">Дуже низький (32)</string>
|
||||
<string name="gpu_swizzlechunk_low">Низький (64)</string>
|
||||
<string name="gpu_swizzlechunk_normal">Нормальний (128)</string>
|
||||
<string name="gpu_swizzlechunk_medium">Середній (256)</string>
|
||||
<string name="gpu_swizzlechunk_high">Високий (512)</string>
|
||||
|
||||
<!-- Temperature Units -->
|
||||
<string name="temperature_celsius">Цельсій</string>
|
||||
|
||||
@@ -947,10 +947,25 @@
|
||||
<string name="fast_gpu_high">高 (512)</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">极小 (16 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_small">较小 (32 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_normal">正常 (128 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_large">较大 (256 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_verylarge">极大 (512 MB)</string>
|
||||
|
||||
<!-- GPU swizzle streams -->
|
||||
<string name="gpu_swizzle_verylow">极低 (4 MB)</string>
|
||||
<string name="gpu_swizzle_low">低 (8 MB)</string>
|
||||
<string name="gpu_swizzle_normal">正常 (16 MB)</string>
|
||||
<string name="gpu_swizzle_medium">中 (32 MB)</string>
|
||||
<string name="gpu_swizzle_high">高 (64 MB)</string>
|
||||
|
||||
<!-- GPU swizzle chunks -->
|
||||
<string name="gpu_swizzlechunk_verylow">极低 (32)</string>
|
||||
<string name="gpu_swizzlechunk_low">低 (64)</string>
|
||||
<string name="gpu_swizzlechunk_normal">正常 (128)</string>
|
||||
<string name="gpu_swizzlechunk_medium">中 (256)</string>
|
||||
<string name="gpu_swizzlechunk_high">高 (512)</string>
|
||||
|
||||
<!-- Temperature Units -->
|
||||
<string name="temperature_celsius">摄氏度</string>
|
||||
|
||||
@@ -545,6 +545,54 @@
|
||||
<item>2</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="gpuTextureSizeSwizzleEntries">
|
||||
<item>@string/gpu_texturesizeswizzle_verysmall</item>
|
||||
<item>@string/gpu_texturesizeswizzle_small</item>
|
||||
<item>@string/gpu_texturesizeswizzle_normal</item>
|
||||
<item>@string/gpu_texturesizeswizzle_large</item>
|
||||
<item>@string/gpu_texturesizeswizzle_verylarge</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="gpuTextureSizeSwizzleValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="gpuSwizzleEntries">
|
||||
<item>@string/gpu_swizzle_verylow</item>
|
||||
<item>@string/gpu_swizzle_low</item>
|
||||
<item>@string/gpu_swizzle_normal</item>
|
||||
<item>@string/gpu_swizzle_medium</item>
|
||||
<item>@string/gpu_swizzle_high</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="gpuSwizzleValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="gpuSwizzleChunkEntries">
|
||||
<item>@string/gpu_swizzlechunk_verylow</item>
|
||||
<item>@string/gpu_swizzlechunk_low</item>
|
||||
<item>@string/gpu_swizzlechunk_normal</item>
|
||||
<item>@string/gpu_swizzlechunk_medium</item>
|
||||
<item>@string/gpu_swizzlechunk_high</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="gpuSwizzleChunkValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<item>3</item>
|
||||
<item>4</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="temperatureUnitEntries">
|
||||
<item>@string/temperature_celsius</item>
|
||||
<item>@string/temperature_fahrenheit</item>
|
||||
|
||||
@@ -524,7 +524,10 @@
|
||||
<string name="rescale_hack_description">Enables a legacy handling for the rescale configuration pass for games by using a quick rescale path</string>
|
||||
<string name="renderer_asynchronous_shaders">Use asynchronous shaders</string>
|
||||
<string name="renderer_asynchronous_shaders_description">Compiles shaders asynchronously. This may reduce stutters but may also introduce glitches.</string>
|
||||
<string name="gpu_unswizzle_settings">GPU Unswizzle Settings</string>
|
||||
<string name="gpu_unswizzle_settings_description">Configure GPU-based texture unswizzling parameters or disable it entirely. Adjust these settings to balance performance and texture loading quality.</string>
|
||||
<string name="gpu_unswizzle_enable">Enable GPU Unswizzle</string>
|
||||
<string name="gpu_unswizzle_disabled">Disabled</string>
|
||||
<string name="gpu_unswizzle_texture_size">GPU Unswizzle Max Texture Size</string>
|
||||
<string name="gpu_unswizzle_texture_size_description">Sets the maximum size (MB) for GPU-based texture unswizzling. While the GPU is faster for medium and large textures, the CPU may be more efficient for very small ones. Adjust this to find the balance between GPU acceleration and CPU overhead.</string>
|
||||
<string name="gpu_unswizzle_stream_size">GPU Unswizzle Stream Size</string>
|
||||
@@ -975,10 +978,25 @@
|
||||
<string name="fast_gpu_high">High (512)</string>
|
||||
|
||||
<!-- GPU swizzle texture size -->
|
||||
<string name="gpu_texturesizeswizzle_verysmall">Very Small (16 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_small">Small (32 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_normal">Normal (128 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_large">Large (256 MB)</string>
|
||||
<string name="gpu_texturesizeswizzle_verylarge">Very Large (512 MB)</string>
|
||||
|
||||
<!-- GPU swizzle streams -->
|
||||
<string name="gpu_swizzle_verylow">Very Low (4 MB)</string>
|
||||
<string name="gpu_swizzle_low">Low (8 MB)</string>
|
||||
<string name="gpu_swizzle_normal">Normal (16 MB)</string>
|
||||
<string name="gpu_swizzle_medium">Medium (32 MB)</string>
|
||||
<string name="gpu_swizzle_high">High (64 MB)</string>
|
||||
|
||||
<!-- GPU swizzle chunks -->
|
||||
<string name="gpu_swizzlechunk_verylow">Very Low (32)</string>
|
||||
<string name="gpu_swizzlechunk_low">Low (64)</string>
|
||||
<string name="gpu_swizzlechunk_normal">Normal (128)</string>
|
||||
<string name="gpu_swizzlechunk_medium">Medium (256)</string>
|
||||
<string name="gpu_swizzlechunk_high">High (512)</string>
|
||||
|
||||
<!-- Temperature Units -->
|
||||
<string name="temperature_celsius">Celsius</string>
|
||||
|
||||
@@ -22,9 +22,11 @@ using namespace std::literals;
|
||||
constexpr auto INCREMENT_TIME{5ms};
|
||||
|
||||
DeviceSession::DeviceSession(Core::System& system_)
|
||||
: system{system_}, thread_event{Core::Timing::CreateEvent(
|
||||
"AudioOutSampleTick",
|
||||
[this](s64 time, std::chrono::nanoseconds) { return ThreadFunc(); })} {}
|
||||
: system{system_}
|
||||
, thread_event{system_.CreateTimingEvent("AudioOutSampleTick", [this](s64 time, std::chrono::nanoseconds) {
|
||||
return ThreadFunc();
|
||||
})}
|
||||
{}
|
||||
|
||||
DeviceSession::~DeviceSession() {
|
||||
Finalize();
|
||||
|
||||
+9
-15
@@ -584,29 +584,23 @@ struct Values {
|
||||
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
|
||||
Category::RendererHacks};
|
||||
|
||||
SwitchableSetting<u32, true> gpu_unswizzle_texture_size{linkage,
|
||||
6,
|
||||
1,
|
||||
9,
|
||||
SwitchableSetting<GpuUnswizzleSize> gpu_unswizzle_texture_size{linkage,
|
||||
GpuUnswizzleSize::Large,
|
||||
"gpu_unswizzle_texture_size",
|
||||
Category::RendererHacks,
|
||||
Specialization::Scalar};
|
||||
Specialization::Default};
|
||||
|
||||
SwitchableSetting<u32, true> gpu_unswizzle_stream_size{linkage,
|
||||
4,
|
||||
1,
|
||||
9,
|
||||
SwitchableSetting<GpuUnswizzle> gpu_unswizzle_stream_size{linkage,
|
||||
GpuUnswizzle::Medium,
|
||||
"gpu_unswizzle_stream_size",
|
||||
Category::RendererHacks,
|
||||
Specialization::Scalar};
|
||||
Specialization::Default};
|
||||
|
||||
SwitchableSetting<u32, true> gpu_unswizzle_chunk_size{linkage,
|
||||
7,
|
||||
1,
|
||||
9,
|
||||
SwitchableSetting<GpuUnswizzleChunk> gpu_unswizzle_chunk_size{linkage,
|
||||
GpuUnswizzleChunk::Medium,
|
||||
"gpu_unswizzle_chunk_size",
|
||||
Category::RendererHacks,
|
||||
Specialization::Scalar};
|
||||
Specialization::Default};
|
||||
|
||||
SwitchableSetting<bool> gpu_unswizzle_enabled{linkage, false, "gpu_unswizzle_enabled",
|
||||
Category::RendererHacks};
|
||||
|
||||
@@ -152,6 +152,9 @@ ENUM(ConsoleMode, Handheld, Docked);
|
||||
ENUM(AppletMode, HLE, LLE);
|
||||
ENUM(SpirvOptimizeMode, Never, OnLoad, Always);
|
||||
ENUM(GpuOverclock, Normal, Medium, High)
|
||||
ENUM(GpuUnswizzleSize, VerySmall, Small, Normal, Large, VeryLarge)
|
||||
ENUM(GpuUnswizzle, VeryLow, Low, Normal, Medium, High)
|
||||
ENUM(GpuUnswizzleChunk, VeryLow, Low, Normal, Medium, High)
|
||||
ENUM(TemperatureUnits, Celsius, Fahrenheit)
|
||||
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2, EDS3);
|
||||
ENUM(GpuLogLevel, Off, Errors, Standard, Verbose, All)
|
||||
|
||||
@@ -969,4 +969,8 @@ void System::ApplySettings() {
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Core::Timing::EventType> System::CreateTimingEvent(std::string name, Core::Timing::TimedCallback&& callback) {
|
||||
return std::make_shared<Core::Timing::EventType>(std::move(callback), std::move(name));
|
||||
}
|
||||
|
||||
} // namespace Core
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "core/file_sys/vfs/vfs_types.h"
|
||||
#include "core/hle/service/os/event.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/core_timing.h"
|
||||
|
||||
namespace Core::Frontend {
|
||||
class EmuWindow;
|
||||
@@ -438,6 +439,9 @@ public:
|
||||
/// Applies any changes to settings to this core instance.
|
||||
void ApplySettings();
|
||||
|
||||
std::shared_ptr<Core::Timing::EventType> CreateTimingEvent(std::string name, Core::Timing::TimedCallback&& callback);
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
+14
-45
@@ -23,10 +23,6 @@ namespace Core::Timing {
|
||||
|
||||
constexpr s64 MAX_SLICE_LENGTH = 10000;
|
||||
|
||||
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
|
||||
return std::make_shared<EventType>(std::move(callback), std::move(name));
|
||||
}
|
||||
|
||||
struct CoreTiming::Event {
|
||||
s64 time;
|
||||
u64 fifo_order;
|
||||
@@ -36,11 +32,10 @@ struct CoreTiming::Event {
|
||||
|
||||
// Sort by time, unless the times are the same, in which case sort by
|
||||
// the order added to the queue
|
||||
friend bool operator>(const Event& left, const Event& right) {
|
||||
friend bool operator>(const Event& left, const Event& right) noexcept {
|
||||
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order);
|
||||
}
|
||||
|
||||
friend bool operator<(const Event& left, const Event& right) {
|
||||
friend bool operator<(const Event& left, const Event& right) noexcept {
|
||||
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order);
|
||||
}
|
||||
};
|
||||
@@ -60,8 +55,6 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
|
||||
Common::SetCurrentThreadName("HostTiming");
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
||||
on_thread_init();
|
||||
has_started = true;
|
||||
|
||||
// base frequency in MHz: 1ns (10^-9) = 1GHz (10^9)
|
||||
while (!stop_token.stop_requested()) {
|
||||
while (!paused && !stop_token.stop_requested()) {
|
||||
@@ -77,8 +70,8 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
|
||||
// continue.
|
||||
wait_set = true;
|
||||
event.Wait();
|
||||
wait_set = false;
|
||||
}
|
||||
wait_set = false;
|
||||
}
|
||||
paused_set = true;
|
||||
pause_event.Wait();
|
||||
@@ -144,39 +137,28 @@ void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
|
||||
event.Set();
|
||||
}
|
||||
|
||||
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time,
|
||||
std::chrono::nanoseconds resched_time,
|
||||
const std::shared_ptr<EventType>& event_type,
|
||||
bool absolute_time) {
|
||||
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, std::chrono::nanoseconds resched_time, const std::shared_ptr<EventType>& event_type, bool absolute_time) {
|
||||
{
|
||||
std::scoped_lock scope{basic_lock};
|
||||
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time};
|
||||
|
||||
auto h{event_queue.emplace(
|
||||
Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()})};
|
||||
auto h = event_queue.emplace(Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()});
|
||||
(*h).handle = h;
|
||||
}
|
||||
|
||||
event.Set();
|
||||
}
|
||||
|
||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
|
||||
UnscheduleEventType type) {
|
||||
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, UnscheduleEventType type) {
|
||||
{
|
||||
std::scoped_lock lk{basic_lock};
|
||||
|
||||
std::vector<heap_t::handle_type> to_remove;
|
||||
for (auto itr = event_queue.begin(); itr != event_queue.end(); itr++) {
|
||||
const Event& e = *itr;
|
||||
for (auto it = event_queue.begin(); it != event_queue.end(); it++) {
|
||||
auto const& e = *it;
|
||||
if (e.type.lock().get() == event_type.get()) {
|
||||
to_remove.push_back(itr->handle);
|
||||
to_remove.push_back(it->handle);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& h : to_remove) {
|
||||
for (auto& h : to_remove)
|
||||
event_queue.erase(h);
|
||||
}
|
||||
|
||||
event_type->sequence_number++;
|
||||
}
|
||||
|
||||
@@ -187,16 +169,15 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
|
||||
}
|
||||
|
||||
static u64 GetNextTickCount(u64 next_ticks) {
|
||||
if (Settings::values.use_custom_cpu_ticks.GetValue()) {
|
||||
if (Settings::values.use_custom_cpu_ticks.GetValue())
|
||||
return Settings::values.cpu_ticks.GetValue();
|
||||
}
|
||||
return next_ticks;
|
||||
}
|
||||
|
||||
void CoreTiming::AddTicks(u64 ticks_to_add) {
|
||||
const u64 ticks = GetNextTickCount(ticks_to_add);
|
||||
cpu_ticks += ticks;
|
||||
downcount -= static_cast<s64>(ticks);
|
||||
downcount -= s64(ticks);
|
||||
}
|
||||
|
||||
void CoreTiming::Idle() {
|
||||
@@ -270,19 +251,14 @@ std::optional<s64> CoreTiming::Advance() {
|
||||
next_time = pause_end_time + next_schedule_time;
|
||||
}
|
||||
|
||||
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type,
|
||||
next_schedule_time, evt.handle});
|
||||
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type, next_schedule_time, evt.handle});
|
||||
}
|
||||
}
|
||||
|
||||
global_timer = GetGlobalTimeNs().count();
|
||||
}
|
||||
|
||||
if (!event_queue.empty()) {
|
||||
return event_queue.top().time;
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
return event_queue.empty() ? std::optional<s64>{} : event_queue.top().time;
|
||||
}
|
||||
|
||||
void CoreTiming::Reset() {
|
||||
@@ -293,7 +269,6 @@ void CoreTiming::Reset() {
|
||||
timer_thread.request_stop();
|
||||
timer_thread.join();
|
||||
}
|
||||
has_started = false;
|
||||
}
|
||||
|
||||
/// @brief Returns current time in nanoseconds.
|
||||
@@ -310,10 +285,4 @@ std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const noexcept {
|
||||
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void CoreTiming::SetTimerResolutionNs(std::chrono::nanoseconds ns) {
|
||||
timer_resolution_ns = ns.count();
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Core::Timing
|
||||
|
||||
+11
-33
@@ -29,8 +29,7 @@ using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>(
|
||||
|
||||
/// Contains the characteristics of a particular event.
|
||||
struct EventType {
|
||||
explicit EventType(TimedCallback&& callback_, std::string&& name_)
|
||||
: callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
|
||||
explicit EventType(TimedCallback&& callback_, std::string&& name_) : callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
|
||||
|
||||
/// The event's callback function.
|
||||
TimedCallback callback;
|
||||
@@ -90,11 +89,6 @@ public:
|
||||
/// Checks if core timing is running.
|
||||
bool IsRunning() const;
|
||||
|
||||
/// Checks if the timer thread has started.
|
||||
bool HasStarted() const {
|
||||
return has_started;
|
||||
}
|
||||
|
||||
/// Checks if there are any pending time events.
|
||||
bool HasPendingEvents() const;
|
||||
|
||||
@@ -134,45 +128,29 @@ public:
|
||||
/// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
|
||||
std::optional<s64> Advance();
|
||||
|
||||
#ifdef _WIN32
|
||||
void SetTimerResolutionNs(std::chrono::nanoseconds ns);
|
||||
#endif
|
||||
|
||||
struct Event;
|
||||
|
||||
void Reset();
|
||||
|
||||
using heap_t = boost::heap::fibonacci_heap<CoreTiming::Event, boost::heap::compare<std::greater<>>>;
|
||||
Common::Event event{};
|
||||
Common::Event pause_event{};
|
||||
|
||||
alignas(64) mutable std::mutex basic_lock;
|
||||
alignas(64) std::mutex advance_lock;
|
||||
alignas(64) std::atomic<bool> paused{};
|
||||
alignas(64) std::atomic<bool> paused_set{};
|
||||
alignas(64) std::atomic<bool> wait_set{};
|
||||
std::function<void()> on_thread_init{};
|
||||
heap_t event_queue;
|
||||
std::jthread timer_thread;
|
||||
s64 global_timer = 0;
|
||||
#ifdef _WIN32
|
||||
s64 timer_resolution_ns;
|
||||
#endif
|
||||
u64 event_fifo_id = 0;
|
||||
s64 pause_end_time{};
|
||||
/// Cycle timing
|
||||
u64 cpu_ticks{};
|
||||
s64 downcount{};
|
||||
Common::Event event{};
|
||||
Common::Event pause_event{};
|
||||
std::function<void()> on_thread_init{};
|
||||
std::jthread timer_thread;
|
||||
mutable std::mutex basic_lock;
|
||||
std::mutex advance_lock;
|
||||
std::atomic<bool> paused{};
|
||||
std::atomic<bool> paused_set{};
|
||||
std::atomic<bool> wait_set{};
|
||||
std::atomic<bool> has_started{};
|
||||
bool is_multicore{};
|
||||
};
|
||||
|
||||
/// Creates a core timing event with the given name and callback.
|
||||
///
|
||||
/// @param name The name of the core timing event to create.
|
||||
/// @param callback The callback to execute for the event.
|
||||
///
|
||||
/// @returns An EventType instance representing the created event.
|
||||
///
|
||||
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback);
|
||||
|
||||
} // namespace Core::Timing
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
@@ -13,11 +13,10 @@ namespace Kernel {
|
||||
|
||||
void KHardwareTimer::Initialize() {
|
||||
// Create the timing callback to register with CoreTiming.
|
||||
m_event_type = Core::Timing::CreateEvent("KHardwareTimer::Callback",
|
||||
[this](s64, std::chrono::nanoseconds) {
|
||||
this->DoTask();
|
||||
return std::nullopt;
|
||||
});
|
||||
m_event_type = m_kernel.System().CreateTimingEvent("KHardwareTimer::Callback", [this](s64, std::chrono::nanoseconds) {
|
||||
this->DoTask();
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
void KHardwareTimer::Finalize() {
|
||||
|
||||
@@ -255,7 +255,7 @@ struct KernelCore::Impl {
|
||||
}
|
||||
|
||||
void InitializePreemption(KernelCore& kernel) {
|
||||
preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
|
||||
preemption_event = system.CreateTimingEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
|
||||
{
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
global_scheduler_context->PreemptThreads(kernel);
|
||||
|
||||
@@ -25,16 +25,11 @@ AlarmWorker::~AlarmWorker() {
|
||||
|
||||
void AlarmWorker::Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m) {
|
||||
m_time_m = std::move(time_m);
|
||||
|
||||
m_timer_event = m_ctx.CreateEvent("Glue:AlarmWorker:TimerEvent");
|
||||
m_timer_timing_event = Core::Timing::CreateEvent(
|
||||
"Glue:AlarmWorker::AlarmTimer",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_event->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
m_timer_timing_event = m_system.CreateTimingEvent("Glue:AlarmWorker::AlarmTimer", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_event->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
AttachToClosestAlarmEvent();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,28 +22,19 @@ namespace Service::Glue::Time {
|
||||
|
||||
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
|
||||
FileTimestampWorker& file_timestamp_worker)
|
||||
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent(
|
||||
"Glue:TimeWorker:Event")},
|
||||
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent("Glue:TimeWorker:Event")},
|
||||
m_steady_clock_resource{steady_clock_resource},
|
||||
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent(
|
||||
"Glue:TimeWorker:SteadyClockTimerEvent")},
|
||||
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent("Glue:TimeWorker:SteadyClockTimerEvent")},
|
||||
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
|
||||
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
|
||||
m_timer_steady_clock_timing_event = Core::Timing::CreateEvent(
|
||||
"Time::SteadyClockEvent",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_steady_clock->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
m_timer_file_system_timing_event = Core::Timing::CreateEvent(
|
||||
"Time::SteadyClockEvent",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_file_system->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
m_timer_steady_clock_timing_event = m_system.CreateTimingEvent("Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_steady_clock->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
m_timer_file_system_timing_event = m_system.CreateTimingEvent("Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_timer_file_system->Signal(m_system.Kernel());
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
TimeWorker::~TimeWorker() {
|
||||
|
||||
@@ -51,17 +51,12 @@ Hidbus::Hidbus(Core::System& system_)
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// Register update callbacks
|
||||
hidbus_update_event = Core::Timing::CreateEvent(
|
||||
"Hidbus::UpdateCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
const auto guard = LockService();
|
||||
UpdateHidbus(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns,
|
||||
hidbus_update_event);
|
||||
hidbus_update_event = system_.CreateTimingEvent("Hidbus::UpdateCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
const auto guard = LockService();
|
||||
UpdateHidbus(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns, hidbus_update_event);
|
||||
}
|
||||
|
||||
Hidbus::~Hidbus() {
|
||||
|
||||
@@ -23,25 +23,17 @@ Conductor::Conductor(Core::System& system, Container& container, DisplayList& di
|
||||
});
|
||||
|
||||
if (system.IsMulticore()) {
|
||||
m_event = Core::Timing::CreateEvent(
|
||||
"ScreenComposition",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_signal.Set();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
|
||||
m_event = system.CreateTimingEvent("ScreenComposition", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
m_signal.Set();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
|
||||
m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); });
|
||||
} else {
|
||||
m_event = Core::Timing::CreateEvent(
|
||||
"ScreenComposition",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
this->ProcessVsync();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
|
||||
m_event = system.CreateTimingEvent("ScreenComposition", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
this->ProcessVsync();
|
||||
return std::chrono::nanoseconds(this->GetNextTicks());
|
||||
});
|
||||
system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,12 +231,10 @@ CheatEngine::~CheatEngine() {
|
||||
}
|
||||
|
||||
void CheatEngine::Initialize() {
|
||||
event = Core::Timing::CreateEvent(
|
||||
"CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
|
||||
[this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
event = system.CreateTimingEvent("CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id), [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, event);
|
||||
|
||||
metadata.process_id = system.ApplicationProcess()->GetProcessId();
|
||||
|
||||
@@ -52,14 +52,12 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
|
||||
Freezer::Freezer(Core::System& system_, Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
|
||||
: core_timing{core_timing_}, memory{memory_} {
|
||||
event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
|
||||
[this](s64 time, std::chrono::nanoseconds ns_late)
|
||||
-> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
event = system_.CreateTimingEvent("MemoryFreezer::FrameCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
FrameCallback(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
core_timing.ScheduleEvent(memory_freezer_ns, event);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -11,14 +14,16 @@
|
||||
#include <vector>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Core::Timing {
|
||||
namespace Core {
|
||||
class System;
|
||||
namespace Timing {
|
||||
class CoreTiming;
|
||||
struct EventType;
|
||||
} // namespace Core::Timing
|
||||
|
||||
namespace Core::Memory {
|
||||
namespace Memory {
|
||||
class Memory;
|
||||
}
|
||||
} //namespace Core::Memory
|
||||
} //namespace Core
|
||||
|
||||
namespace Tools {
|
||||
|
||||
@@ -38,7 +43,7 @@ public:
|
||||
u64 value;
|
||||
};
|
||||
|
||||
explicit Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_);
|
||||
explicit Freezer(Core::System& system_, Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_);
|
||||
~Freezer();
|
||||
|
||||
// Enables or disables the entire memory freezer.
|
||||
|
||||
@@ -56,33 +56,22 @@ ResourceManager::ResourceManager(Core::System& system_,
|
||||
applet_resource = std::make_shared<AppletResource>(system);
|
||||
|
||||
// Register update callbacks
|
||||
npad_update_event = Core::Timing::CreateEvent("HID::UpdatePadCallback",
|
||||
[this](s64 time, std::chrono::nanoseconds ns_late)
|
||||
-> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateNpad(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
default_update_event = Core::Timing::CreateEvent(
|
||||
"HID::UpdateDefaultCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateControllers(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
mouse_keyboard_update_event = Core::Timing::CreateEvent(
|
||||
"HID::UpdateMouseKeyboardCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMouseKeyboard(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
motion_update_event = Core::Timing::CreateEvent(
|
||||
"HID::UpdateMotionCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMotion(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
npad_update_event = system.CreateTimingEvent("HID::UpdatePadCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateNpad(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
default_update_event = system.CreateTimingEvent("HID::UpdateDefaultCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateControllers(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
mouse_keyboard_update_event = system.CreateTimingEvent("HID::UpdateMouseKeyboardCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMouseKeyboard(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
motion_update_event = system.CreateTimingEvent("HID::UpdateMotionCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
UpdateMotion(ns_late);
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
|
||||
ResourceManager::~ResourceManager() {
|
||||
@@ -267,13 +256,10 @@ void ResourceManager::InitializeTouchScreenSampler() {
|
||||
touch_screen = std::make_shared<TouchScreen>(touch_resource);
|
||||
gesture = std::make_shared<Gesture>(touch_resource);
|
||||
|
||||
touch_update_event = Core::Timing::CreateEvent(
|
||||
"HID::TouchUpdateCallback",
|
||||
[this](s64 time,
|
||||
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
touch_resource->OnTouchUpdate(time);
|
||||
return std::nullopt;
|
||||
});
|
||||
touch_update_event = system.CreateTimingEvent("HID::TouchUpdateCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
|
||||
touch_resource->OnTouchUpdate(time);
|
||||
return std::nullopt;
|
||||
});
|
||||
|
||||
touch_resource->SetTouchDriver(touch_driver);
|
||||
touch_resource->SetAppletResource(applet_resource, &shared_mutex);
|
||||
|
||||
@@ -240,16 +240,16 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
|
||||
tr("Accelerates BCn 3D texture decoding using GPU compute.\n"
|
||||
"Disable if experiencing crashes or graphical glitches."));
|
||||
INSERT(Settings, gpu_unswizzle_texture_size, tr("GPU Unswizzle Max Texture Size"),
|
||||
tr("Sets the maximum size (power of 2 * 1MiB) for GPU-based texture unswizzling.\n"
|
||||
tr("Sets the maximum size (MiB) for GPU-based texture unswizzling.\n"
|
||||
"While the GPU is faster for medium and large textures, the CPU may be more "
|
||||
"efficient for very small ones.\n"
|
||||
"Adjust this to find the balance between GPU acceleration and CPU overhead."));
|
||||
INSERT(Settings, gpu_unswizzle_stream_size, tr("GPU Unswizzle Stream Size"),
|
||||
tr("Sets the maximum amount of texture data (power of 2 * 1MiB) processed per frame.\n"
|
||||
tr("Sets the maximum amount of texture data (in MiB) processed per frame.\n"
|
||||
"Higher values can reduce stutter during texture loading but may impact frame "
|
||||
"consistency."));
|
||||
INSERT(Settings, gpu_unswizzle_chunk_size, tr("GPU Unswizzle Chunk Size"),
|
||||
tr("Determines the number of depth slices (power of 2) processed in a single dispatch.\n"
|
||||
tr("Determines the number of depth slices processed in a single dispatch.\n"
|
||||
"Increasing this can improve throughput on high-end GPUs but may cause TDR or driver "
|
||||
"timeouts on weaker hardware."));
|
||||
|
||||
@@ -652,6 +652,31 @@ std::unique_ptr<ComboboxTranslationMap> ComboboxEnumeration(QObject* parent) {
|
||||
PAIR(GpuOverclock, Medium, tr("Medium (256)")),
|
||||
PAIR(GpuOverclock, High, tr("High (512)")),
|
||||
}});
|
||||
translations->insert({Settings::EnumMetadata<Settings::GpuUnswizzleSize>::Index(),
|
||||
{
|
||||
PAIR(GpuUnswizzleSize, VerySmall, tr("Very Small (16 MB)")),
|
||||
PAIR(GpuUnswizzleSize, Small, tr("Small (32 MB)")),
|
||||
PAIR(GpuUnswizzleSize, Normal, tr("Normal (128 MB)")),
|
||||
PAIR(GpuUnswizzleSize, Large, tr("Large (256 MB)")),
|
||||
PAIR(GpuUnswizzleSize, VeryLarge, tr("Very Large (512 MB)")),
|
||||
}});
|
||||
translations->insert({Settings::EnumMetadata<Settings::GpuUnswizzle>::Index(),
|
||||
{
|
||||
PAIR(GpuUnswizzle, VeryLow, tr("Very Low (4 MB)")),
|
||||
PAIR(GpuUnswizzle, Low, tr("Low (8 MB)")),
|
||||
PAIR(GpuUnswizzle, Normal, tr("Normal (16 MB)")),
|
||||
PAIR(GpuUnswizzle, Medium, tr("Medium (32 MB)")),
|
||||
PAIR(GpuUnswizzle, High, tr("High (64 MB)")),
|
||||
}});
|
||||
translations->insert({Settings::EnumMetadata<Settings::GpuUnswizzleChunk>::Index(),
|
||||
{
|
||||
PAIR(GpuUnswizzleChunk, VeryLow, tr("Very Low (32)")),
|
||||
PAIR(GpuUnswizzleChunk, Low, tr("Low (64)")),
|
||||
PAIR(GpuUnswizzleChunk, Normal, tr("Normal (128)")),
|
||||
PAIR(GpuUnswizzleChunk, Medium, tr("Medium (256)")),
|
||||
PAIR(GpuUnswizzleChunk, High, tr("High (512)")),
|
||||
}});
|
||||
|
||||
translations->insert({Settings::EnumMetadata<Settings::ExtendedDynamicState>::Index(),
|
||||
{
|
||||
PAIR(ExtendedDynamicState, Disabled, tr("Disabled")),
|
||||
|
||||
@@ -266,12 +266,7 @@ void Init(QWidget* root) {
|
||||
Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
|
||||
LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB});
|
||||
#ifdef _WIN32
|
||||
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms",
|
||||
std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(
|
||||
Common::Windows::SetCurrentTimerResolutionToMaximum())
|
||||
.count());
|
||||
QtCommon::system->CoreTiming().SetTimerResolutionNs(
|
||||
Common::Windows::GetCurrentTimerResolution());
|
||||
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(Common::Windows::SetCurrentTimerResolutionToMaximum()).count());
|
||||
#endif
|
||||
|
||||
// Remove cached contents generated during the previous session
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2016 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -53,14 +56,15 @@ u64 TestTimerSpeed(Core::Timing::CoreTiming& core_timing) {
|
||||
} // Anonymous namespace
|
||||
|
||||
TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
|
||||
Core::System system{};
|
||||
ScopeInit guard;
|
||||
auto& core_timing = guard.core_timing;
|
||||
std::vector<std::shared_ptr<Core::Timing::EventType>> events{
|
||||
Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
|
||||
Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
|
||||
Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
|
||||
Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
|
||||
Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
|
||||
system.CreateTimingEvent("callbackA", HostCallbackTemplate<0>),
|
||||
system.CreateTimingEvent("callbackB", HostCallbackTemplate<1>),
|
||||
system.CreateTimingEvent("callbackC", HostCallbackTemplate<2>),
|
||||
system.CreateTimingEvent("callbackD", HostCallbackTemplate<3>),
|
||||
system.CreateTimingEvent("callbackE", HostCallbackTemplate<4>),
|
||||
};
|
||||
|
||||
expected_callback = 0;
|
||||
@@ -93,14 +97,15 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
|
||||
}
|
||||
|
||||
TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
|
||||
Core::System system{};
|
||||
ScopeInit guard;
|
||||
auto& core_timing = guard.core_timing;
|
||||
std::vector<std::shared_ptr<Core::Timing::EventType>> events{
|
||||
Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>),
|
||||
Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>),
|
||||
Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>),
|
||||
Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>),
|
||||
Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>),
|
||||
system.CreateTimingEvent("callbackA", HostCallbackTemplate<0>),
|
||||
system.CreateTimingEvent("callbackB", HostCallbackTemplate<1>),
|
||||
system.CreateTimingEvent("callbackC", HostCallbackTemplate<2>),
|
||||
system.CreateTimingEvent("callbackD", HostCallbackTemplate<3>),
|
||||
system.CreateTimingEvent("callbackE", HostCallbackTemplate<4>),
|
||||
};
|
||||
|
||||
core_timing.SyncPause(true);
|
||||
|
||||
@@ -77,10 +77,35 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag
|
||||
minimum_memory = 0;
|
||||
}
|
||||
|
||||
if (Settings::values.gpu_unswizzle_enabled.GetValue()) {
|
||||
gpu_unswizzle_maxsize = (1 << u32(Settings::values.gpu_unswizzle_texture_size.GetValue())) * 1_MiB;
|
||||
swizzle_chunk_size = (1 << u32(Settings::values.gpu_unswizzle_stream_size.GetValue())) * 1_MiB;
|
||||
swizzle_slices_per_batch = 1 << u32(Settings::values.gpu_unswizzle_chunk_size.GetValue());
|
||||
const bool gpu_unswizzle_enabled = Settings::values.gpu_unswizzle_enabled.GetValue();
|
||||
|
||||
if (gpu_unswizzle_enabled) {
|
||||
switch (Settings::values.gpu_unswizzle_texture_size.GetValue()) {
|
||||
case Settings::GpuUnswizzleSize::VerySmall: gpu_unswizzle_maxsize = 16_MiB; break;
|
||||
case Settings::GpuUnswizzleSize::Small: gpu_unswizzle_maxsize = 32_MiB; break;
|
||||
case Settings::GpuUnswizzleSize::Normal: gpu_unswizzle_maxsize = 128_MiB; break;
|
||||
case Settings::GpuUnswizzleSize::Large: gpu_unswizzle_maxsize = 256_MiB; break;
|
||||
case Settings::GpuUnswizzleSize::VeryLarge: gpu_unswizzle_maxsize = 512_MiB; break;
|
||||
default: gpu_unswizzle_maxsize = 128_MiB; break;
|
||||
}
|
||||
|
||||
switch (Settings::values.gpu_unswizzle_stream_size.GetValue()) {
|
||||
case Settings::GpuUnswizzle::VeryLow: swizzle_chunk_size = 4_MiB; break;
|
||||
case Settings::GpuUnswizzle::Low: swizzle_chunk_size = 8_MiB; break;
|
||||
case Settings::GpuUnswizzle::Normal: swizzle_chunk_size = 16_MiB; break;
|
||||
case Settings::GpuUnswizzle::Medium: swizzle_chunk_size = 32_MiB; break;
|
||||
case Settings::GpuUnswizzle::High: swizzle_chunk_size = 64_MiB; break;
|
||||
default: swizzle_chunk_size = 16_MiB;
|
||||
}
|
||||
|
||||
switch (Settings::values.gpu_unswizzle_chunk_size.GetValue()) {
|
||||
case Settings::GpuUnswizzleChunk::VeryLow: swizzle_slices_per_batch = 32; break;
|
||||
case Settings::GpuUnswizzleChunk::Low: swizzle_slices_per_batch = 64; break;
|
||||
case Settings::GpuUnswizzleChunk::Normal: swizzle_slices_per_batch = 128; break;
|
||||
case Settings::GpuUnswizzleChunk::Medium: swizzle_slices_per_batch = 256; break;
|
||||
case Settings::GpuUnswizzleChunk::High: swizzle_slices_per_batch = 512; break;
|
||||
default: swizzle_slices_per_batch = 128;
|
||||
}
|
||||
} else {
|
||||
gpu_unswizzle_maxsize = 0;
|
||||
swizzle_chunk_size = 0;
|
||||
|
||||
@@ -371,7 +371,6 @@ int main(int argc, char** argv) {
|
||||
|
||||
#ifdef _WIN32
|
||||
Common::Windows::SetCurrentTimerResolutionToMaximum();
|
||||
system.CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
|
||||
#endif
|
||||
|
||||
system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
|
||||
|
||||
Reference in New Issue
Block a user