Compare commits

..

9 Commits

Author SHA1 Message Date
lizzie 0f8effc22a use scalar 2026-07-03 17:56:36 +00:00
lizzie b930951254 value hint 2026-07-03 17:56:36 +00:00
lizzie 0a38913d9c android 2026-07-03 17:56:36 +00:00
lizzie 481e0e450d [common] make unswizzle settings be able to be configured for all powers of 2 from 2^1 to 2^16
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-07-03 17:55:43 +00:00
lizzie 4c65780f11 Revert "[common/dynamic_library] fix AUR build error (#4156)" (#4157)
This reverts commit a9c4c8aefd.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4157
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-07-02 22:07:37 +02:00
lizzie a9c4c8aefd [common/dynamic_library] fix AUR build error (#4156)
not gonna question why there was an ifdef there

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4156
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-07-02 19:49:19 +02:00
lizzie a769505a45 [vk, ogl] Remove dedicated precomputed swizzle table; use shorter inline table in block_linear swizzle shaders (#4146)
old table = 64 * 8 * sizeof(u32) = 512 * 4 = 4096 bytes
new table = 8 * sizeof(u32) = 8 * 4 = 32 bytes

the expression
```glsl
    return ((pos & 0x0180) >> 1)
         | ((pos & 0x0040) >> 2)
         | ((pos & 0x0020) << 3)
         | ((pos & 0x0010) << 1)
         | ((pos & 0x000f) << 0);
```
is equivalent for generating the table but idk if we'd want that

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Co-authored-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4146
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-07-02 19:24:07 +02:00
xbzk 54c3d10b86 [vk, renderdoc] (VUID-02997) avoid vk_image_view as VK_NULL_HANDLE when feature nullDescriptor is unavailable (#4056)
This minor change in src\video_core\renderer_vulkan\pipeline_helper.h allows renderdoc capture on mhr sunbreak.
Maybe it sanitizes some crashes on old vulkan GPUs.

Device log (nvidia kepler gpu vulkan 1.1.117):
[  17.605262] Render.Vulkan <Info> video_core\vulkan_common\vulkan_device.cpp:1041:GetSuitability: Device doesn't support feature nullDescriptor

VUID-VkWriteDescriptorSet-descriptorType-02997
For sampled/combined/storage image descriptors, Khronos says imageView must be valid or VK_NULL_HANDLE
(https://docs.vulkan.org/refpages/latest/refpages/source/VkPhysicalDeviceRobustness2FeaturesKHR.html)

but then it says: if nullDescriptor is not enabled, imageView must not be VK_NULL_HANDLE.
(https://docs.vulkan.org/spec/latest/chapters/descriptorsets.html)
nullDescriptor is exactly the feature that allows descriptors to be written with null handles.

The fix relies on conditionally replacing the null sampled view with Eden’s dummy null-image-view object (ImageView constructor checks HasNullDescriptor which checks features.robustness2.nullDescriptor. cheap checks, and only for null handles, so no notable cost).

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4056
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-07-02 03:23:08 +02:00
xbzk bdf60d79a0 [video_core] gate Mesa EXIT terminator detection behind non-proprietary driver (#4151)
FIXES A REGRESSION FROM 4012.

TryFindSize's Mesa fallback matched the unconditional @PT EXIT (0xE30000000007000F) that nv50_ir emits at program end.
That exact word is also emitted by NVN mid-program for unconditional early-outs, so on retail titles (e.g. Super Mario 3D World) the scan truncated at the first early EXIT and dropped the rest of the shader, making textures vanish.

Mesa's terminal EXIT and NVN's mid-program EXIT are bit-identical, so no mask can separate them. Gate the heuristic on !is_proprietary_driver:

NVN binaries (bindless cbuf slot 2) keep self-branch-only sizing, while nouveau/Mesa homebrew (single terminal EXIT, no self-branch trailer) still uses the EXIT terminator. nv50_ir emits exactly one EXIT (early returns lower to BRA-to-exit, discard to DISCARD), so a single terminal match is correct for that path.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4151
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-07-01 13:06:00 +02:00
31 changed files with 180 additions and 875 deletions
@@ -1,89 +0,0 @@
// 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()
}
@@ -686,42 +686,33 @@ abstract class SettingsItem(
)
)
put(
SingleChoiceSetting(
SpinBoxSetting(
IntSetting.GPU_UNSWIZZLE_TEXTURE_SIZE,
titleId = R.string.gpu_unswizzle_texture_size,
descriptionId = R.string.gpu_unswizzle_texture_size_description,
choicesId = R.array.gpuTextureSizeSwizzleEntries,
valuesId = R.array.gpuTextureSizeSwizzleValues
valueHint = R.string.gpu_unswizzle_texture_size,
min = 1,
max = 9
)
)
put(
SingleChoiceSetting(
SpinBoxSetting(
IntSetting.GPU_UNSWIZZLE_STREAM_SIZE,
titleId = R.string.gpu_unswizzle_stream_size,
descriptionId = R.string.gpu_unswizzle_stream_size_description,
choicesId = R.array.gpuSwizzleEntries,
valuesId = R.array.gpuSwizzleValues
valueHint = R.string.gpu_unswizzle_stream_size,
min = 1,
max = 9
)
)
put(
SingleChoiceSetting(
SpinBoxSetting(
IntSetting.GPU_UNSWIZZLE_CHUNK_SIZE,
titleId = R.string.gpu_unswizzle_chunk_size,
descriptionId = R.string.gpu_unswizzle_chunk_size_description,
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
valueHint = R.string.gpu_unswizzle_chunk_size,
min = 1,
max = 9
)
)
put(
@@ -1,206 +0,0 @@
// 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
}
}
}
@@ -102,10 +102,6 @@ class SettingsAdapter(
PathViewHolder(ListItemSettingBinding.inflate(inflater), this)
}
SettingsItem.TYPE_GPU_UNSWIZZLE -> {
GpuUnswizzleViewHolder(ListItemSettingBinding.inflate(inflater), this)
}
else -> {
HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)
}
@@ -479,14 +475,6 @@ 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
@@ -1,71 +0,0 @@
// 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,10 +516,7 @@
<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>
@@ -957,25 +954,10 @@
<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,25 +890,10 @@ 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,10 +510,7 @@
<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>
@@ -951,25 +948,10 @@
<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,10 +509,7 @@
<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>
@@ -950,25 +947,10 @@
<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,10 +512,7 @@
<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>
@@ -953,25 +950,10 @@
<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,25 +947,10 @@
<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,54 +545,6 @@
<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,10 +524,7 @@
<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>
@@ -978,25 +975,10 @@
<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>
+15 -9
View File
@@ -584,23 +584,29 @@ struct Values {
SwitchableSetting<bool> use_asynchronous_shaders{linkage, false, "use_asynchronous_shaders",
Category::RendererHacks};
SwitchableSetting<GpuUnswizzleSize> gpu_unswizzle_texture_size{linkage,
GpuUnswizzleSize::Large,
SwitchableSetting<u32, true> gpu_unswizzle_texture_size{linkage,
6,
1,
9,
"gpu_unswizzle_texture_size",
Category::RendererHacks,
Specialization::Default};
Specialization::Scalar};
SwitchableSetting<GpuUnswizzle> gpu_unswizzle_stream_size{linkage,
GpuUnswizzle::Medium,
SwitchableSetting<u32, true> gpu_unswizzle_stream_size{linkage,
4,
1,
9,
"gpu_unswizzle_stream_size",
Category::RendererHacks,
Specialization::Default};
Specialization::Scalar};
SwitchableSetting<GpuUnswizzleChunk> gpu_unswizzle_chunk_size{linkage,
GpuUnswizzleChunk::Medium,
SwitchableSetting<u32, true> gpu_unswizzle_chunk_size{linkage,
7,
1,
9,
"gpu_unswizzle_chunk_size",
Category::RendererHacks,
Specialization::Default};
Specialization::Scalar};
SwitchableSetting<bool> gpu_unswizzle_enabled{linkage, false, "gpu_unswizzle_enabled",
Category::RendererHacks};
-3
View File
@@ -152,9 +152,6 @@ 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)
+3 -28
View File
@@ -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 (MiB) for GPU-based texture unswizzling.\n"
tr("Sets the maximum size (power of 2 * 1MiB) 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 (in MiB) processed per frame.\n"
tr("Sets the maximum amount of texture data (power of 2 * 1MiB) 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 processed in a single dispatch.\n"
tr("Determines the number of depth slices (power of 2) 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,31 +652,6 @@ 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")),
@@ -11,9 +11,8 @@
#define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants {
#define END_PUSH_CONSTANTS };
#define UNIFORM(n)
#define BINDING_SWIZZLE_BUFFER 0
#define BINDING_INPUT_BUFFER 1
#define BINDING_OUTPUT_IMAGE 2
#define BINDING_INPUT_BUFFER 0
#define BINDING_OUTPUT_IMAGE 1
#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
@@ -26,8 +25,7 @@
#define BEGIN_PUSH_CONSTANTS
#define END_PUSH_CONSTANTS
#define UNIFORM(n) layout (location = n) uniform
#define BINDING_SWIZZLE_BUFFER 0
#define BINDING_INPUT_BUFFER 1
#define BINDING_INPUT_BUFFER 0
#define BINDING_OUTPUT_IMAGE 0
#endif
@@ -43,10 +41,6 @@ UNIFORM(6) uint block_height;
UNIFORM(7) uint block_height_mask;
END_PUSH_CONSTANTS
layout(binding = BINDING_SWIZZLE_BUFFER, std430) readonly buffer SwizzleTable {
uint swizzle_table[];
};
#if HAS_EXTENDED_TYPES
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU8 { uint8_t u8data[]; };
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU16 { uint16_t u16data[]; };
@@ -71,9 +65,19 @@ const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHI
const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1, GOB_SIZE_Y - 1);
uint SwizzleTable(uint pos) {
const uint t[8] = uint[](
0x12100200, 0x13110301, 0x16140604, 0x17150705,
0x1a180a08, 0x1b190b09, 0x1e1c0e0c, 0x1f1d0f0d
);
const uint i = pos >> 4;
const uint h = (t[i / 4] >> ((i % 4) * 8)) & 0xff;
return (h << 4) | (pos & 0xf);
}
uint SwizzleOffset(uvec2 pos) {
pos = pos & SWIZZLE_MASK;
return swizzle_table[pos.y * 64 + pos.x];
return SwizzleTable(pos.y * 64 + pos.x);
}
uvec4 ReadTexel(uint offset) {
@@ -11,9 +11,8 @@
#define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants {
#define END_PUSH_CONSTANTS };
#define UNIFORM(n)
#define BINDING_SWIZZLE_BUFFER 0
#define BINDING_INPUT_BUFFER 1
#define BINDING_OUTPUT_IMAGE 2
#define BINDING_INPUT_BUFFER 0
#define BINDING_OUTPUT_IMAGE 1
#else // ^^^ Vulkan ^^^ // vvv OpenGL vvv
@@ -26,8 +25,7 @@
#define BEGIN_PUSH_CONSTANTS
#define END_PUSH_CONSTANTS
#define UNIFORM(n) layout (location = n) uniform
#define BINDING_SWIZZLE_BUFFER 0
#define BINDING_INPUT_BUFFER 1
#define BINDING_INPUT_BUFFER 0
#define BINDING_OUTPUT_IMAGE 0
#endif
@@ -45,10 +43,6 @@ UNIFORM(8) uint block_depth;
UNIFORM(9) uint block_depth_mask;
END_PUSH_CONSTANTS
layout(binding = BINDING_SWIZZLE_BUFFER, std430) readonly buffer SwizzleTable {
uint swizzle_table[];
};
#if HAS_EXTENDED_TYPES
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU8 { uint8_t u8data[]; };
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU16 { uint16_t u16data[]; };
@@ -73,9 +67,19 @@ const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHI
const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1, GOB_SIZE_Y - 1);
uint SwizzleTable(uint pos) {
const uint t[8] = uint[](
0x12100200, 0x13110301, 0x16140604, 0x17150705,
0x1a180a08, 0x1b190b09, 0x1e1c0e0c, 0x1f1d0f0d
);
const uint i = pos >> 4;
const uint h = (t[i / 4] >> ((i % 4) * 8)) & 0xff;
return (h << 4) | (pos & 0xf);
}
uint SwizzleOffset(uvec2 pos) {
pos = pos & SWIZZLE_MASK;
return swizzle_table[pos.y * 64 + pos.x];
return SwizzleTable(pos.y * 64 + pos.x);
}
uvec4 ReadTexel(uint offset) {
@@ -10,9 +10,8 @@
#define BEGIN_PUSH_CONSTANTS layout(push_constant) uniform PushConstants {
#define END_PUSH_CONSTANTS };
#define UNIFORM(n)
#define BINDING_SWIZZLE_BUFFER 0
#define BINDING_INPUT_BUFFER 1
#define BINDING_OUTPUT_BUFFER 2
#define BINDING_INPUT_BUFFER 0
#define BINDING_OUTPUT_BUFFER 1
#else
#extension GL_NV_gpu_shader5 : enable
#ifdef GL_NV_gpu_shader5
@@ -23,7 +22,6 @@
#define BEGIN_PUSH_CONSTANTS
#define END_PUSH_CONSTANTS
#define UNIFORM(n) layout(location = n) uniform
#define BINDING_SWIZZLE_BUFFER 0
#define BINDING_INPUT_BUFFER 1
#define BINDING_OUTPUT_BUFFER 0
#endif
@@ -66,13 +64,9 @@ END_PUSH_CONSTANTS
#endif
// --- Buffers ---
layout(binding = BINDING_SWIZZLE_BUFFER, std430) readonly buffer SwizzleTable {
uint swizzle_table[];
};
#if HAS_EXTENDED_TYPES
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU8 { uint8_t u8data[]; };
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU16 { uint16_t u16data[]; };
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU8 { uint8_t u8data[]; };
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU16 { uint16_t u16data[]; };
#endif
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU32 { uint u32data[]; };
layout(binding = BINDING_INPUT_BUFFER, std430) buffer InputBufferU64 { uvec2 u64data[]; };
@@ -96,10 +90,20 @@ const uint GOB_SIZE_Z_SHIFT = 0;
const uint GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_SHIFT;
const uvec2 SWIZZLE_MASK = uvec2(GOB_SIZE_X - 1u, GOB_SIZE_Y - 1u);
uint SwizzleTable(uint pos) {
const uint t[8] = uint[](
0x12100200, 0x13110301, 0x16140604, 0x17150705,
0x1a180a08, 0x1b190b09, 0x1e1c0e0c, 0x1f1d0f0d
);
const uint i = pos >> 4;
const uint h = (t[i / 4] >> ((i % 4) * 8)) & 0xff;
return (h << 4) | (pos & 0xf);
}
// --- Helpers ---
uint SwizzleOffset(uvec2 pos) {
pos &= SWIZZLE_MASK;
return swizzle_table[pos.y * 64u + pos.x];
return SwizzleTable(pos.y * 64u + pos.x);
}
uvec4 ReadTexel(uint offset) {
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -56,10 +59,8 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_)
copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)),
convert_s8d24_program(MakeProgram(OPENGL_CONVERT_S8D24_COMP)),
convert_ms_to_nonms_program(MakeProgram(CONVERT_MSAA_TO_NON_MSAA_COMP)),
convert_nonms_to_ms_program(MakeProgram(CONVERT_NON_MSAA_TO_MSAA_COMP)) {
const auto swizzle_table = Tegra::Texture::MakeSwizzleTable();
swizzle_table_buffer.Create();
glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0);
convert_nonms_to_ms_program(MakeProgram(CONVERT_NON_MSAA_TO_MSAA_COMP))
{
}
UtilShaders::~UtilShaders() = default;
@@ -116,13 +117,11 @@ void UtilShaders::ASTCDecode(Image& image, const StagingBufferMap& map,
void UtilShaders::BlockLinearUpload2D(Image& image, const StagingBufferMap& map,
std::span<const SwizzleParameters> swizzles) {
static constexpr Extent3D WORKGROUP_SIZE{32, 32, 1};
static constexpr GLuint BINDING_SWIZZLE_BUFFER = 0;
static constexpr GLuint BINDING_INPUT_BUFFER = 1;
static constexpr GLuint BINDING_INPUT_BUFFER = 0;
static constexpr GLuint BINDING_OUTPUT_IMAGE = 0;
program_manager.BindComputeProgram(block_linear_unswizzle_2d_program.handle);
glFlushMappedNamedBufferRange(map.buffer, map.offset, image.guest_size_bytes);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_SWIZZLE_BUFFER, swizzle_table_buffer.handle);
const GLenum store_format = StoreFormat(BytesPerBlock(image.info.format));
for (const SwizzleParameters& swizzle : swizzles) {
@@ -153,14 +152,11 @@ void UtilShaders::BlockLinearUpload2D(Image& image, const StagingBufferMap& map,
void UtilShaders::BlockLinearUpload3D(Image& image, const StagingBufferMap& map,
std::span<const SwizzleParameters> swizzles) {
static constexpr Extent3D WORKGROUP_SIZE{16, 8, 8};
static constexpr GLuint BINDING_SWIZZLE_BUFFER = 0;
static constexpr GLuint BINDING_INPUT_BUFFER = 1;
static constexpr GLuint BINDING_INPUT_BUFFER = 0;
static constexpr GLuint BINDING_OUTPUT_IMAGE = 0;
glFlushMappedNamedBufferRange(map.buffer, map.offset, image.guest_size_bytes);
program_manager.BindComputeProgram(block_linear_unswizzle_3d_program.handle);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, BINDING_SWIZZLE_BUFFER, swizzle_table_buffer.handle);
const GLenum store_format = StoreFormat(BytesPerBlock(image.info.format));
for (const SwizzleParameters& swizzle : swizzles) {
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -45,9 +48,6 @@ public:
private:
ProgramManager& program_manager;
OGLBuffer swizzle_table_buffer;
OGLProgram astc_decoder_program;
OGLProgram block_linear_unswizzle_2d_program;
OGLProgram block_linear_unswizzle_3d_program;
@@ -203,7 +203,11 @@ inline void PushImageDescriptors(TextureCache& texture_cache,
const VideoCommon::ImageViewId image_view_id{(views++)->id};
const VideoCommon::SamplerId sampler_id{*(samplers++)};
ImageView& image_view{texture_cache.GetImageView(image_view_id)};
const VkImageView vk_image_view{image_view.Handle(desc.type)};
VkImageView vk_image_view{image_view.Handle(desc.type)};
if (vk_image_view == VK_NULL_HANDLE) {
const VkImageView null_image_view{texture_cache.GetImageView(VideoCommon::NULL_IMAGE_VIEW_ID).Handle(desc.type)};
if (null_image_view != VK_NULL_HANDLE) vk_image_view = null_image_view;
}
const Sampler& sampler{texture_cache.GetSampler(sampler_id)};
const bool use_fallback_sampler{sampler.HasAddedAnisotropy() &&
!image_view.SupportsAnisotropy()};
@@ -653,71 +653,8 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
scheduler.Finish();
}
constexpr u32 BL3D_BINDING_SWIZZLE_TABLE = 0;
constexpr u32 BL3D_BINDING_INPUT_BUFFER = 1;
constexpr u32 BL3D_BINDING_OUTPUT_BUFFER = 2;
constexpr std::array<VkDescriptorSetLayoutBinding, 3> BL3D_DESCRIPTOR_SET_BINDINGS{{
{
.binding = BL3D_BINDING_SWIZZLE_TABLE,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // swizzle_table[]
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.pImmutableSamplers = nullptr,
},
{
.binding = BL3D_BINDING_INPUT_BUFFER,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // block-linear input
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.pImmutableSamplers = nullptr,
},
{
.binding = BL3D_BINDING_OUTPUT_BUFFER,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.pImmutableSamplers = nullptr,
},
}};
constexpr DescriptorBankInfo BL3D_BANK_INFO{
.uniform_buffers = 0,
.storage_buffers = 3,
.texture_buffers = 0,
.image_buffers = 0,
.textures = 0,
.images = 0,
.score = 3,
};
constexpr std::array<VkDescriptorUpdateTemplateEntry, 3>
BL3D_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY{{
{
.dstBinding = BL3D_BINDING_SWIZZLE_TABLE,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.offset = BL3D_BINDING_SWIZZLE_TABLE * sizeof(DescriptorUpdateEntry),
.stride = sizeof(DescriptorUpdateEntry),
},
{
.dstBinding = BL3D_BINDING_INPUT_BUFFER,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.offset = BL3D_BINDING_INPUT_BUFFER * sizeof(DescriptorUpdateEntry),
.stride = sizeof(DescriptorUpdateEntry),
},
{
.dstBinding = BL3D_BINDING_OUTPUT_BUFFER,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.offset = BL3D_BINDING_OUTPUT_BUFFER * sizeof(DescriptorUpdateEntry),
.stride = sizeof(DescriptorUpdateEntry),
}
}};
constexpr u32 BL3D_BINDING_INPUT_BUFFER = 0;
constexpr u32 BL3D_BINDING_OUTPUT_BUFFER = 1;
struct alignas(16) BlockLinearUnswizzle3DPushConstants {
u32 blocks_dim[3]; // Offset 0
@@ -745,11 +682,50 @@ BlockLinearUnswizzle3DPass::BlockLinearUnswizzle3DPass(
DescriptorPool& descriptor_pool_,
StagingBufferPool& staging_buffer_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(
device_, scheduler_, descriptor_pool_,
BL3D_DESCRIPTOR_SET_BINDINGS,
BL3D_DESCRIPTOR_UPDATE_TEMPLATE_ENTRY,
BL3D_BANK_INFO,
: ComputePass(device_, scheduler_, descriptor_pool_,
std::array<VkDescriptorSetLayoutBinding, 2>{{
{
.binding = BL3D_BINDING_INPUT_BUFFER,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // block-linear input
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.pImmutableSamplers = nullptr,
},
{
.binding = BL3D_BINDING_OUTPUT_BUFFER,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_COMPUTE_BIT,
.pImmutableSamplers = nullptr,
},
}},
std::array<VkDescriptorUpdateTemplateEntry, 2>{{
{
.dstBinding = BL3D_BINDING_INPUT_BUFFER,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.offset = BL3D_BINDING_INPUT_BUFFER * sizeof(DescriptorUpdateEntry),
.stride = sizeof(DescriptorUpdateEntry),
},
{
.dstBinding = BL3D_BINDING_OUTPUT_BUFFER,
.dstArrayElement = 0,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.offset = BL3D_BINDING_OUTPUT_BUFFER * sizeof(DescriptorUpdateEntry),
.stride = sizeof(DescriptorUpdateEntry),
}
}},
DescriptorBankInfo{
.uniform_buffers = 0,
.storage_buffers = 2,
.texture_buffers = 0,
.image_buffers = 0,
.textures = 0,
.images = 0,
.score = 2,
},
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(BlockLinearUnswizzle3DPushConstants)>,
BLOCK_LINEAR_UNSWIZZLE_3D_BCN_COMP_SPV),
scheduler{scheduler_},
@@ -822,8 +798,6 @@ void BlockLinearUnswizzle3DPass::UnswizzleChunk(
pc.blocks_dim[2] = z_count; // Only process the count
compute_pass_descriptor_queue.Acquire(scheduler, 3);
compute_pass_descriptor_queue.AddBuffer(*image.runtime->swizzle_table_buffer, 0,
image.runtime->swizzle_table_size);
compute_pass_descriptor_queue.AddBuffer(swizzled.buffer,
sw.buffer_offset + swizzled.offset,
image.guest_size_bytes - sw.buffer_offset);
@@ -909,40 +909,6 @@ TextureCacheRuntime::TextureCacheRuntime(const Device& device_, Scheduler& sched
bl3d_unswizzle_pass.emplace(device, scheduler, descriptor_pool,
staging_buffer_pool, compute_pass_descriptor_queue);
}
// --- Create swizzle table buffer ---
{
auto table = Tegra::Texture::MakeSwizzleTable();
swizzle_table_size = static_cast<VkDeviceSize>(table.size() * sizeof(table[0]));
auto staging = staging_buffer_pool.Request(swizzle_table_size, MemoryUsage::Upload);
std::memcpy(staging.mapped_span.data(), table.data(), static_cast<size_t>(swizzle_table_size));
VkBufferCreateInfo ci{
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = swizzle_table_size,
.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
};
swizzle_table_buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::DeviceLocal);
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([staging_buf = staging.buffer,
dst_buf = *swizzle_table_buffer,
size = swizzle_table_size,
src_off = staging.offset](vk::CommandBuffer cmdbuf) {
const VkBufferCopy region{
.srcOffset = src_off,
.dstOffset = 0,
.size = size,
};
cmdbuf.CopyBuffer(staging_buf, dst_buf, region);
});
}
}
void TextureCacheRuntime::Finish() {
@@ -2314,46 +2280,29 @@ vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_
}
Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) {
const bool has_custom_border_ext = runtime.device.IsExtCustomBorderColorSupported();
const bool has_format_undefined = has_custom_border_ext && runtime.device.IsCustomBorderColorWithoutFormatSupported();
const bool has_custom_border_colors = has_format_undefined && runtime.device.IsCustomBorderColorsSupported();
const bool has_border_color_swizzle = has_custom_border_ext && runtime.device.IsExtBorderColorSwizzleSupported();
const auto& device = runtime.device;
const bool has_custom_border_extension = runtime.device.IsExtCustomBorderColorSupported();
const bool has_format_undefined =
has_custom_border_extension && runtime.device.IsCustomBorderColorWithoutFormatSupported();
const bool has_custom_border_colors =
has_format_undefined && runtime.device.IsCustomBorderColorsSupported();
const auto color = tsc.BorderColor();
const void* pnext = nullptr;
const VkSamplerCustomBorderColorCreateInfoEXT border_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
.pNext = pnext,
.pNext = nullptr,
.customBorderColor = std::bit_cast<VkClearColorValue>(color),
.format = VK_FORMAT_UNDEFINED,
};
const void* pnext = nullptr;
if (has_custom_border_colors) {
pnext = &border_ci;
// Log extension usage for custom border color
if (GPU::Logging::IsActive()) {
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage("VK_EXT_custom_border_color", "Sampler::Sampler");
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage(
"VK_EXT_custom_border_color", "Sampler::Sampler");
}
}
const VkSamplerBorderColorComponentMappingCreateInfoEXT border_swizzle_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT,
.pNext = pnext,
.components = VkComponentMapping{
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
},
.srgb = tsc.srgb_conversion
};
if (has_border_color_swizzle) {
pnext = &border_swizzle_ci;
// Log extension usage for custom border color
if (GPU::Logging::IsActive()) {
GPU::Logging::GPULogger::GetInstance().LogExtensionUsage("VK_EXT_border_color_swizzle", "Sampler::Sampler");
}
}
const VkSamplerReductionModeCreateInfoEXT reduction_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO_EXT,
.pNext = pnext,
@@ -2364,33 +2313,36 @@ Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& t
} else if (reduction_ci.reductionMode != VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE_EXT) {
LOG_WARNING(Render_Vulkan, "VK_EXT_sampler_filter_minmax is required");
}
// Some games have samplers with garbage. Sanitize them here.
const f32 max_anisotropy = std::clamp(tsc.MaxAnisotropy(), 1.0f, 16.0f);
const auto create_sampler = [&](const f32 anisotropy) {
return runtime.device.GetLogical().CreateSampler(VkSamplerCreateInfo{
return device.GetLogical().CreateSampler(VkSamplerCreateInfo{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
.pNext = pnext,
.flags = 0,
.magFilter = MaxwellToVK::Sampler::Filter(tsc.mag_filter),
.minFilter = MaxwellToVK::Sampler::Filter(tsc.min_filter),
.mipmapMode = MaxwellToVK::Sampler::MipmapMode(tsc.mipmap_filter),
.addressModeU = MaxwellToVK::Sampler::WrapMode(runtime.device, tsc.wrap_u, tsc.mag_filter),
.addressModeV = MaxwellToVK::Sampler::WrapMode(runtime.device, tsc.wrap_v, tsc.mag_filter),
.addressModeW = MaxwellToVK::Sampler::WrapMode(runtime.device, tsc.wrap_p, tsc.mag_filter),
.addressModeU = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_u, tsc.mag_filter),
.addressModeV = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_v, tsc.mag_filter),
.addressModeW = MaxwellToVK::Sampler::WrapMode(device, tsc.wrap_p, tsc.mag_filter),
.mipLodBias = tsc.LodBias(),
.anisotropyEnable = VkBool32(anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
.anisotropyEnable = static_cast<VkBool32>(anisotropy > 1.0f ? VK_TRUE : VK_FALSE),
.maxAnisotropy = anisotropy,
.compareEnable = tsc.depth_compare_enabled,
.compareOp = MaxwellToVK::Sampler::DepthCompareFunction(tsc.depth_compare_func),
.minLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.0f : tsc.MinLod(),
.maxLod = tsc.mipmap_filter == TextureMipmapFilter::None ? 0.25f : tsc.MaxLod(),
.borderColor = has_custom_border_colors ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT : ConvertBorderColor(color),
.borderColor = has_custom_border_colors ? VK_BORDER_COLOR_FLOAT_CUSTOM_EXT
: ConvertBorderColor(color),
.unnormalizedCoordinates = VK_FALSE,
});
};
sampler = create_sampler(max_anisotropy);
const f32 max_anisotropy_default = f32(1U << tsc.max_anisotropy);
const f32 max_anisotropy_default = static_cast<f32>(1U << tsc.max_anisotropy);
if (max_anisotropy > max_anisotropy_default) {
sampler_default_anisotropy = create_sampler(max_anisotropy_default);
}
@@ -2498,18 +2450,13 @@ void TextureCacheRuntime::AccelerateImageUpload(
if (!Settings::values.gpu_unswizzle_enabled.GetValue() || !bl3d_unswizzle_pass) {
if (IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D) {
ASSERT_MSG(false, "GPU unswizzle is disabled for BCn 3D texture");
ASSERT(false && "GPU unswizzle is disabled for BCn 3D texture");
}
ASSERT(false);
return;
}
if (bl3d_unswizzle_pass &&
IsPixelFormatBCn(image.info.format) &&
image.info.type == ImageType::e3D &&
image.info.resources.levels == 1 &&
image.info.resources.layers == 1) {
if (bl3d_unswizzle_pass && IsPixelFormatBCn(image.info.format) && image.info.type == ImageType::e3D && image.info.resources.levels == 1 && image.info.resources.layers == 1) {
return bl3d_unswizzle_pass->Unswizzle(image, map, swizzles, z_start, z_count);
}
@@ -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 2019 yuzu Emulator Project
@@ -130,9 +130,6 @@ public:
std::optional<ASTCDecoderPass> astc_decoder_pass;
std::optional<BlockLinearUnswizzle3DPass> bl3d_unswizzle_pass;
vk::Buffer swizzle_table_buffer;
VkDeviceSize swizzle_table_size = 0;
std::optional<MSAACopyPass> msaa_copy_pass;
const Settings::ResolutionScalingInfo& resolution;
std::array<std::vector<VkFormat>, VideoCore::Surface::MaxPixelFormat> view_formats;
+2 -3
View File
@@ -255,8 +255,7 @@ std::optional<u64> GenericEnvironment::TryFindSize() {
static constexpr u64 SELF_BRANCH_A = 0xE2400FFFFF87000FULL;
static constexpr u64 SELF_BRANCH_B = 0xE2400FFFFF07000FULL;
static constexpr u64 MESA_EXIT_MASK = 0xFFF00000000F001FULL;
static constexpr u64 MESA_EXIT_VALUE = (0xE30ULL << 52) | (0x7ULL << 16) | 0xFULL;
static constexpr u64 EXIT_VALUE = 0xE30000000007000FULL;
code.resize(MAXIMUM_SIZE / INST_SIZE);
@@ -271,7 +270,7 @@ std::optional<u64> GenericEnvironment::TryFindSize() {
if (inst == SELF_BRANCH_A || inst == SELF_BRANCH_B) {
return offset + index;
}
if ((inst & MESA_EXIT_MASK) == MESA_EXIT_VALUE) {
if (!is_proprietary_driver && inst == EXIT_VALUE) {
return offset + index + INST_SIZE;
}
}
+4 -29
View File
@@ -77,35 +77,10 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag
minimum_memory = 0;
}
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;
}
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());
} else {
gpu_unswizzle_maxsize = 0;
swizzle_chunk_size = 0;
+3 -18
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -23,24 +26,6 @@ constexpr u32 GOB_SIZE_SHIFT = GOB_SIZE_X_SHIFT + GOB_SIZE_Y_SHIFT + GOB_SIZE_Z_
constexpr u32 SWIZZLE_X_BITS = 0b100101111;
constexpr u32 SWIZZLE_Y_BITS = 0b011010000;
using SwizzleTable = std::array<std::array<u32, GOB_SIZE_X>, GOB_SIZE_Y>;
/**
* This table represents the internal swizzle of a gob, in format 16 bytes x 2 sector packing.
* Calculates the offset of an (x, y) position within a swizzled texture.
* Taken from the Tegra X1 Technical Reference Manual. pages 1187-1188
*/
constexpr SwizzleTable MakeSwizzleTable() {
SwizzleTable table{};
for (u32 y = 0; y < table.size(); ++y) {
for (u32 x = 0; x < table[0].size(); ++x) {
table[y][x] = ((x % 64) / 32) * 256 + ((y % 8) / 2) * 64 + ((x % 32) / 16) * 32 +
(y % 2) * 16 + (x % 16);
}
}
return table;
}
/// Unswizzles a block linear texture into linear memory.
void UnswizzleTexture(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixel,
u32 width, u32 height, u32 depth, u32 block_height, u32 block_depth,
+8 -11
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@@ -55,16 +55,13 @@ namespace {
} // Anonymous namespace
std::array<float, 4> TSCEntry::BorderColor() const noexcept {
if (!srgb_conversion)
return border_color;
// SRGB will be handled by custom border color swizzle
// if not, we are in big, big trouble and may break shadows on Xenoblade
return {
f32(srgb_border_color_r) / 255.f,
f32(srgb_border_color_g) / 255.f,
f32(srgb_border_color_b) / 255.f,
border_color[3]
};
// TODO: Handle SRGB correctly. Using this breaks shadows in some games (Xenoblade).
// if (!srgb_conversion) {
// return border_color;
//}
// return {SRGB_CONVERSION_LUT[srgb_border_color_r], SRGB_CONVERSION_LUT[srgb_border_color_g],
// SRGB_CONVERSION_LUT[srgb_border_color_b], border_color[3]};
return border_color;
}
float TSCEntry::MaxAnisotropy() const noexcept {
@@ -1172,10 +1172,12 @@ bool Device::GetSuitability(bool requires_swapchain) {
void Device::RemoveUnsuitableExtensions() {
// VK_EXT_custom_border_color
if (extensions.custom_border_color) {
extensions.custom_border_color = features.custom_border_color.customBorderColors
&& features.custom_border_color.customBorderColorWithoutFormat;
extensions.custom_border_color =
features.custom_border_color.customBorderColors &&
features.custom_border_color.customBorderColorWithoutFormat;
}
RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color,
VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
// VK_EXT_depth_bias_control
extensions.depth_bias_control =
@@ -50,7 +50,6 @@ VK_DEFINE_HANDLE(VmaAllocator)
// Define all features which may be used by the implementation and require an extension here.
#define FOR_EACH_VK_FEATURE_EXT(FEATURE) \
FEATURE(EXT, CustomBorderColor, CUSTOM_BORDER_COLOR, custom_border_color) \
FEATURE(EXT, BorderColorSwizzle, BORDER_COLOR_SWIZZLE, border_color_swizzle) \
FEATURE(EXT, DepthBiasControl, DEPTH_BIAS_CONTROL, depth_bias_control) \
FEATURE(EXT, DepthClipControl, DEPTH_CLIP_CONTROL, depth_clip_control) \
FEATURE(EXT, ExtendedDynamicState, EXTENDED_DYNAMIC_STATE, extended_dynamic_state) \
@@ -583,11 +582,6 @@ FN_MAX_LIMIT_LIST
return features.custom_border_color.customBorderColorWithoutFormat;
}
/// Returns true if the device supports VK_EXT_border_color_swizzle .
bool IsExtBorderColorSwizzleSupported() const {
return extensions.border_color_swizzle;
}
/// Returns true if the device supports VK_EXT_extended_dynamic_state.
bool IsExtExtendedDynamicStateSupported() const {
return extensions.extended_dynamic_state;