mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-29 18:08:08 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b71ddb302a | |||
| 00243891d1 | |||
| 5d42bfba0d | |||
| 42db87998f | |||
| 9a8477eb43 | |||
| 565b04fd12 | |||
| 9941453610 |
+8
-24
@@ -43,7 +43,6 @@ This guide will walk you through adding a new boolean toggle setting to Eden's c
|
|||||||
Firstly add your desired toggle:
|
Firstly add your desired toggle:
|
||||||
|
|
||||||
Example: `src/common/setting.h`
|
Example: `src/common/setting.h`
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
SwitchableSetting<bool> your_setting_name{linkage, false, "your_setting_name", Category::RendererExtensions};
|
SwitchableSetting<bool> your_setting_name{linkage, false, "your_setting_name", Category::RendererExtensions};
|
||||||
```
|
```
|
||||||
@@ -68,7 +67,6 @@ Common Categories:
|
|||||||
Add the toggle to the Qt UI, where you wish for it to appear and place it there.
|
Add the toggle to the Qt UI, where you wish for it to appear and place it there.
|
||||||
|
|
||||||
Example: `src/qt_common/config/shared_translation.cpp`
|
Example: `src/qt_common/config/shared_translation.cpp`
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
INSERT(Settings,
|
INSERT(Settings,
|
||||||
your_setting_name,
|
your_setting_name,
|
||||||
@@ -93,7 +91,6 @@ INSERT(Settings,
|
|||||||
Add where it should be in the settings.
|
Add where it should be in the settings.
|
||||||
|
|
||||||
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt`
|
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt`
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
RENDERER_YOUR_SETTING_NAME("your_setting_name"),
|
RENDERER_YOUR_SETTING_NAME("your_setting_name"),
|
||||||
```
|
```
|
||||||
@@ -109,7 +106,6 @@ RENDERER_YOUR_SETTING_NAME("your_setting_name"),
|
|||||||
Add the toggle to the Kotlin (Android) UI
|
Add the toggle to the Kotlin (Android) UI
|
||||||
|
|
||||||
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt`
|
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt`
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
put(
|
put(
|
||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
@@ -127,7 +123,6 @@ put(
|
|||||||
Add your setting within the right category.
|
Add your setting within the right category.
|
||||||
|
|
||||||
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt`
|
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt`
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
|
add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
|
||||||
```
|
```
|
||||||
@@ -142,7 +137,6 @@ add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
|
|||||||
Add your setting and description in the appropriate place.
|
Add your setting and description in the appropriate place.
|
||||||
|
|
||||||
Example: `src/android/app/src/main/res/values/strings.xml`
|
Example: `src/android/app/src/main/res/values/strings.xml`
|
||||||
|
|
||||||
```xml
|
```xml
|
||||||
<string name="your_setting_name">Your Setting Display Name</string>
|
<string name="your_setting_name">Your Setting Display Name</string>
|
||||||
<string name="your_setting_name_description">Detailed description of what this setting does. Explain any caveats, requirements, or warnings here.</string>
|
<string name="your_setting_name_description">Detailed description of what this setting does. Explain any caveats, requirements, or warnings here.</string>
|
||||||
@@ -156,7 +150,6 @@ Now the UI part is done find a place in the code for the toggle,
|
|||||||
And use it to your heart's desire!
|
And use it to your heart's desire!
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
const bool your_value = Settings::values.your_setting_name.GetValue();
|
const bool your_value = Settings::values.your_setting_name.GetValue();
|
||||||
|
|
||||||
@@ -203,31 +196,25 @@ Common advantages recap:
|
|||||||
|
|
||||||
#### Accessing Debug Knobs (dev side)
|
#### Accessing Debug Knobs (dev side)
|
||||||
|
|
||||||
Use the `Settings::GetDebugKnobAt(u8 i)` function to check if a specific bit is set:
|
Use the `Settings::getDebugKnobAt(u8 i)` function to check if a specific bit is set:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
//cpp side
|
//cpp side
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
|
||||||
//To use it as a general purpose uint var:
|
|
||||||
unsigned int debug_knobs = Settings::values.debug_knobs.GetValue();
|
|
||||||
|
|
||||||
// Check if bit 0 is set
|
// Check if bit 0 is set
|
||||||
bool feature_enabled = Settings::GetDebugKnobAt(0);
|
bool feature_enabled = Settings::getDebugKnobAt(0);
|
||||||
|
|
||||||
// Check if bit 15 is set
|
// Check if bit 15 is set
|
||||||
bool another_feature = Settings::GetDebugKnobAt(15);
|
bool another_feature = Settings::getDebugKnobAt(15);
|
||||||
```
|
```
|
||||||
|
|
||||||
```kts
|
```kts
|
||||||
//kotlin side
|
//kotlin side
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||||
|
|
||||||
//To use it as a general purpose uint var
|
|
||||||
val debug_knobs: Int = UShortSetting.DEBUG_KNOBS.getInt()
|
|
||||||
|
|
||||||
// Check if bit x is set
|
// Check if bit x is set
|
||||||
bool feature_enabled = Settings.GetDebugKnobAt(x); //x as integer from 0 to 15
|
bool feature_enabled = Settings.getDebugKnobAt(x); //x as integer from 0 to 15
|
||||||
```
|
```
|
||||||
|
|
||||||
The function returns `true` if the specified bit (0-15) is set in the `debug_knobs` value, `false` otherwise.
|
The function returns `true` if the specified bit (0-15) is set in the `debug_knobs` value, `false` otherwise.
|
||||||
@@ -260,7 +247,6 @@ There are two main confusions when talking about knobs:
|
|||||||
Sometimes when an user reports: knobs 1 and 2 gets better performance, dev may get confuse whether he means the knobs 1 and 2 literally, or the 1st and 2nd knobs (knobs 0 and 1).
|
Sometimes when an user reports: knobs 1 and 2 gets better performance, dev may get confuse whether he means the knobs 1 and 2 literally, or the 1st and 2nd knobs (knobs 0 and 1).
|
||||||
|
|
||||||
Debug knobs are **zero-based**, which means:
|
Debug knobs are **zero-based**, which means:
|
||||||
|
|
||||||
* The first knob is the knob(0) (or knob0 henceforth), and the last one is the 15 (knob15, likewise)
|
* The first knob is the knob(0) (or knob0 henceforth), and the last one is the 15 (knob15, likewise)
|
||||||
* You can talk: "knob0 is enabled/disabled", "In this video i was using only knobs 0 and 2", etc.
|
* You can talk: "knob0 is enabled/disabled", "In this video i was using only knobs 0 and 2", etc.
|
||||||
|
|
||||||
@@ -273,7 +259,6 @@ Whenever you're instructing tests or reporting results, be precise about whether
|
|||||||
|
|
||||||
ALWAYS use the word in PLURAL (knobs), without mentioning which one, to refer to the setting, aka multiple knobs at once:
|
ALWAYS use the word in PLURAL (knobs), without mentioning which one, to refer to the setting, aka multiple knobs at once:
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
- **knobs=0**: no knobs enabled
|
- **knobs=0**: no knobs enabled
|
||||||
- **knobs=1**: knob0 enabled, others disabled
|
- **knobs=1**: knob0 enabled, others disabled
|
||||||
- **knobs=2**: knob1 enabled, others disabled
|
- **knobs=2**: knob1 enabled, others disabled
|
||||||
@@ -285,7 +270,6 @@ Examples:
|
|||||||
|
|
||||||
Use the word in SINGULAR (knob), or in plural but referring which ones, when meaning multiple knobs at once:
|
Use the word in SINGULAR (knob), or in plural but referring which ones, when meaning multiple knobs at once:
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
- **knob0**: knob 0 enabled, others disabled
|
- **knob0**: knob 0 enabled, others disabled
|
||||||
- **knob1**: knob 1 enabled, others disabled
|
- **knob1**: knob 1 enabled, others disabled
|
||||||
- **knobs 0 and 1**: knobs 0 and 1 enabled, others disabled
|
- **knobs 0 and 1**: knobs 0 and 1 enabled, others disabled
|
||||||
@@ -298,12 +282,12 @@ Examples:
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void SomeFunction() {
|
void SomeFunction() {
|
||||||
if (Settings::GetDebugKnobAt(0)) {
|
if (Settings::getDebugKnobAt(0)) {
|
||||||
LOG_DEBUG(Common, "Debug feature 0 is enabled");
|
LOG_DEBUG(Common, "Debug feature 0 is enabled");
|
||||||
// Additional debug code here
|
// Additional debug code here
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings::GetDebugKnobAt(1)) {
|
if (Settings::getDebugKnobAt(1)) {
|
||||||
LOG_DEBUG(Common, "Debug feature 1 is enabled");
|
LOG_DEBUG(Common, "Debug feature 1 is enabled");
|
||||||
// Different debug behavior
|
// Different debug behavior
|
||||||
}
|
}
|
||||||
@@ -315,7 +299,7 @@ void SomeFunction() {
|
|||||||
```cpp
|
```cpp
|
||||||
bool UseOptimizedPath() {
|
bool UseOptimizedPath() {
|
||||||
// Skip optimization if debug bit 2 is set for testing
|
// Skip optimization if debug bit 2 is set for testing
|
||||||
return !Settings::GetDebugKnobAt(2);
|
return !Settings::getDebugKnobAt(2);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -325,7 +309,7 @@ bool UseOptimizedPath() {
|
|||||||
void ExperimentalFeature() {
|
void ExperimentalFeature() {
|
||||||
static constexpr u8 EXPERIMENTAL_FEATURE_BIT = 3;
|
static constexpr u8 EXPERIMENTAL_FEATURE_BIT = 3;
|
||||||
|
|
||||||
if (!Settings::GetDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
|
if (!Settings::getDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
|
||||||
// Fallback to stable implementation
|
// Fallback to stable implementation
|
||||||
StableImplementation();
|
StableImplementation();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ object NativeLibrary {
|
|||||||
|
|
||||||
external fun refreshThreadPolicies()
|
external fun refreshThreadPolicies()
|
||||||
|
|
||||||
external fun GetDebugKnobAt(index: Int): Boolean
|
external fun getDebugKnobAt(index: Int): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the current speed limit to the configured turbo speed.
|
* Set the current speed limit to the configured turbo speed.
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ object Settings {
|
|||||||
fun getPlayerString(player: Int): String =
|
fun getPlayerString(player: Int): String =
|
||||||
YuzuApplication.appContext.getString(R.string.preferences_player, player)
|
YuzuApplication.appContext.getString(R.string.preferences_player, player)
|
||||||
|
|
||||||
fun GetDebugKnobAt(index: Int): Boolean {
|
fun getDebugKnobAt(index: Int): Boolean {
|
||||||
return org.yuzu.yuzu_emu.NativeLibrary.GetDebugKnobAt(index)
|
return org.yuzu.yuzu_emu.NativeLibrary.getDebugKnobAt(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
|
||||||
|
|||||||
+2
-1
@@ -11,7 +11,8 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
|
|||||||
enum class ShortSetting(override val key: String) : AbstractShortSetting {
|
enum class ShortSetting(override val key: String) : AbstractShortSetting {
|
||||||
RENDERER_SPEED_LIMIT("speed_limit"),
|
RENDERER_SPEED_LIMIT("speed_limit"),
|
||||||
RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"),
|
RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"),
|
||||||
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit")
|
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit"),
|
||||||
|
DEBUG_KNOBS("debug_knobs")
|
||||||
;
|
;
|
||||||
|
|
||||||
override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal)
|
override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal)
|
||||||
|
|||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
package org.yuzu.yuzu_emu.features.settings.model
|
|
||||||
|
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
|
||||||
|
|
||||||
enum class UShortSetting(override val key: String) : AbstractIntSetting {
|
|
||||||
DEBUG_KNOBS("debug_knobs")
|
|
||||||
;
|
|
||||||
|
|
||||||
override fun getInt(needsGlobal: Boolean): Int =
|
|
||||||
NativeConfig.getUnsignedShort(key, needsGlobal)
|
|
||||||
|
|
||||||
override fun setInt(value: Int) {
|
|
||||||
if (NativeConfig.isPerGameConfigLoaded()) {
|
|
||||||
global = false
|
|
||||||
}
|
|
||||||
NativeConfig.setUnsignedShort(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val defaultValue: Int by lazy { NativeConfig.getDefaultToString(key).toInt() }
|
|
||||||
|
|
||||||
override fun getValueAsString(needsGlobal: Boolean): String = getInt(needsGlobal).toString()
|
|
||||||
|
|
||||||
override fun reset() = NativeConfig.setUnsignedShort(key, defaultValue)
|
|
||||||
}
|
|
||||||
+1
-2
@@ -20,7 +20,6 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
|||||||
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
|
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
|
|
||||||
import org.yuzu.yuzu_emu.network.NetDataValidators
|
import org.yuzu.yuzu_emu.network.NetDataValidators
|
||||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
@@ -1035,7 +1034,7 @@ abstract class SettingsItem(
|
|||||||
)
|
)
|
||||||
put(
|
put(
|
||||||
SpinBoxSetting(
|
SpinBoxSetting(
|
||||||
UShortSetting.DEBUG_KNOBS,
|
ShortSetting.DEBUG_KNOBS,
|
||||||
titleId = R.string.debug_knobs,
|
titleId = R.string.debug_knobs,
|
||||||
descriptionId = R.string.debug_knobs_description,
|
descriptionId = R.string.debug_knobs_description,
|
||||||
valueHint = R.string.debug_knobs_hint,
|
valueHint = R.string.debug_knobs_hint,
|
||||||
|
|||||||
+1
-2
@@ -25,7 +25,6 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings
|
|||||||
import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
|
import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
|
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.*
|
import org.yuzu.yuzu_emu.features.settings.model.view.*
|
||||||
import org.yuzu.yuzu_emu.utils.InputHandler
|
import org.yuzu.yuzu_emu.utils.InputHandler
|
||||||
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
|
||||||
@@ -1327,7 +1326,7 @@ class SettingsFragmentPresenter(
|
|||||||
|
|
||||||
add(HeaderSetting(R.string.general))
|
add(HeaderSetting(R.string.general))
|
||||||
|
|
||||||
add(UShortSetting.DEBUG_KNOBS.key)
|
add(ShortSetting.DEBUG_KNOBS.key)
|
||||||
add(StringSetting.PROGRAM_ARGS.key)
|
add(StringSetting.PROGRAM_ARGS.key)
|
||||||
|
|
||||||
if (!NativeConfig.isPerGameConfigLoaded()) {
|
if (!NativeConfig.isPerGameConfigLoaded()) {
|
||||||
|
|||||||
@@ -80,12 +80,6 @@ object NativeConfig {
|
|||||||
@Synchronized
|
@Synchronized
|
||||||
external fun setShort(key: String, value: Short)
|
external fun setShort(key: String, value: Short)
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
external fun getUnsignedShort(key: String, needsGlobal: Boolean): Int
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
external fun setUnsignedShort(key: String, value: Int)
|
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
external fun getInt(key: String, needsGlobal: Boolean): Int
|
external fun getInt(key: String, needsGlobal: Boolean): Int
|
||||||
|
|
||||||
|
|||||||
@@ -1300,8 +1300,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_refreshThreadPolicies(JNIEnv* env, jo
|
|||||||
Common::RefreshThreadPolicies();
|
Common::RefreshThreadPolicies();
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_GetDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
|
||||||
return static_cast<jboolean>(Settings::GetDebugKnobAt(static_cast<u8>(index)));
|
return static_cast<jboolean>(Settings::getDebugKnobAt(static_cast<u8>(index)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
|
||||||
|
|||||||
@@ -130,25 +130,6 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setShort(JNIEnv* env, jobject ob
|
|||||||
setting->SetValue(value);
|
setting->SetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getUnsignedShort(JNIEnv* env, jobject obj,
|
|
||||||
jstring jkey,
|
|
||||||
jboolean needGlobal) {
|
|
||||||
auto setting = getSetting<u16>(env, jkey);
|
|
||||||
if (setting == nullptr) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return static_cast<jint>(setting->GetValue(static_cast<bool>(needGlobal)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setUnsignedShort(JNIEnv* env, jobject obj,
|
|
||||||
jstring jkey, jint value) {
|
|
||||||
auto setting = getSetting<u16>(env, jkey);
|
|
||||||
if (setting == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setting->SetValue(static_cast<u16>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey,
|
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey,
|
||||||
jboolean needGlobal) {
|
jboolean needGlobal) {
|
||||||
auto setting = getSetting<int>(env, jkey);
|
auto setting = getSetting<int>(env, jkey);
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ void LogSettings() {
|
|||||||
#undef LOG_PATH
|
#undef LOG_PATH
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetDebugKnobAt(u8 i) {
|
bool getDebugKnobAt(u8 i) {
|
||||||
return (values.debug_knobs.GetValue() & (1 << (i & 0xF))) != 0;
|
return (values.debug_knobs.GetValue() & (1 << (i & 0xF))) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -904,7 +904,7 @@ struct Values {
|
|||||||
0,
|
0,
|
||||||
65535,
|
65535,
|
||||||
"debug_knobs",
|
"debug_knobs",
|
||||||
Category::System,
|
Category::Debugging,
|
||||||
Specialization::Countable,
|
Specialization::Countable,
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
@@ -947,7 +947,7 @@ constexpr u32 MAX_FRAME_GEN_MULTIPLIER = 4;
|
|||||||
|
|
||||||
[[nodiscard]] size_t FrameGenMaxGenerations();
|
[[nodiscard]] size_t FrameGenMaxGenerations();
|
||||||
|
|
||||||
bool GetDebugKnobAt(u8 i);
|
bool getDebugKnobAt(u8 i);
|
||||||
|
|
||||||
void UpdateGPUAccuracy();
|
void UpdateGPUAccuracy();
|
||||||
bool IsGPULevelHigh();
|
bool IsGPULevelHigh();
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "video_core/vulkan_common/vulkan_device.h"
|
#include "video_core/vulkan_common/vulkan_device.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
#include "video_core/gpu_logging/gpu_logging.h"
|
#include "video_core/gpu_logging/gpu_logging.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
|
||||||
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||||
#include <adrenotools/bcenabler.h>
|
#include <adrenotools/bcenabler.h>
|
||||||
@@ -794,8 +795,55 @@ VkFormat Device::GetSupportedFormat(VkFormat wanted_format, VkFormatFeatureFlags
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Device::ReportLoss() const {
|
void Device::ReportLoss() const {
|
||||||
LOG_CRITICAL(Render_Vulkan, "Device loss occurred!");
|
LOG_CRITICAL(Render_Vulkan, "Device loss occurred! {},{}", extensions.device_fault, features.device_fault.deviceFault);
|
||||||
|
if (extensions.device_fault && features.device_fault.deviceFault) {
|
||||||
|
VkDeviceFaultCountsEXT fault_counts{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_COUNTS_EXT
|
||||||
|
};
|
||||||
|
dld.vkGetDeviceFaultInfoEXT(VkDevice(GetLogical().address()), &fault_counts, nullptr);
|
||||||
|
std::vector<VkDeviceFaultAddressInfoEXT> address_info(fault_counts.addressInfoCount);
|
||||||
|
std::vector<VkDeviceFaultVendorInfoEXT> vendor_info(fault_counts.vendorInfoCount);
|
||||||
|
std::vector<u8> vendor_binary_data(fault_counts.vendorBinarySize);
|
||||||
|
VkDeviceFaultInfoEXT fault_info{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_DEVICE_FAULT_INFO_EXT,
|
||||||
|
.pAddressInfos = address_info.data(),
|
||||||
|
.pVendorInfos = vendor_info.data(),
|
||||||
|
.pVendorBinaryData = vendor_binary_data.data()
|
||||||
|
};
|
||||||
|
dld.vkGetDeviceFaultInfoEXT(VkDevice(GetLogical().address()), &fault_counts, &fault_info);
|
||||||
|
std::string s = "Fault report\n";
|
||||||
|
if (address_info.size() > 0) {
|
||||||
|
s += "address-info\n";
|
||||||
|
for (auto const& ai : address_info) {
|
||||||
|
s += fmt::format("{:#x} => {}\n", ai.reportedAddress, [t = ai.addressType] {
|
||||||
|
switch (t) {
|
||||||
|
#define VKFATC(n) case n: return #n;
|
||||||
|
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_INVALID_EXT)
|
||||||
|
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_FAULT_EXT)
|
||||||
|
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_INSTRUCTION_POINTER_UNKNOWN_EXT)
|
||||||
|
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_WRITE_INVALID_EXT)
|
||||||
|
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_READ_INVALID_EXT)
|
||||||
|
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_EXECUTE_INVALID_EXT)
|
||||||
|
VKFATC(VK_DEVICE_FAULT_ADDRESS_TYPE_NONE_EXT)
|
||||||
|
#undef VKFATC
|
||||||
|
default: return "unknown";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vendor_info.size() > 0) {
|
||||||
|
s += "vendor-info\n";
|
||||||
|
for (auto const& vi : vendor_info)
|
||||||
|
s += fmt::format("{:#x}-{:#x}: {}\n", vi.vendorFaultCode, vi.vendorFaultData, vi.description);
|
||||||
|
}
|
||||||
|
if (vendor_binary_data.size() > 0) {
|
||||||
|
s += "vendor-binary-data\n";
|
||||||
|
for (size_t i = 0; i < vendor_binary_data.size(); ++i)
|
||||||
|
s += fmt::format("{:02x} ", vendor_binary_data[i]);
|
||||||
|
s += "\n";
|
||||||
|
}
|
||||||
|
LOG_INFO(Render_Vulkan, "{}", s);
|
||||||
|
}
|
||||||
// Wait for the log to flush and for Nsight Aftermath to dump the results
|
// Wait for the log to flush and for Nsight Aftermath to dump the results
|
||||||
std::this_thread::sleep_for(std::chrono::seconds{15});
|
std::this_thread::sleep_for(std::chrono::seconds{15});
|
||||||
}
|
}
|
||||||
@@ -926,13 +974,13 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
|||||||
|
|
||||||
#define EXTENSION(prefix, macro_name, var_name) \
|
#define EXTENSION(prefix, macro_name, var_name) \
|
||||||
if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \
|
if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \
|
||||||
loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \
|
loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \
|
||||||
extensions.var_name = true; \
|
extensions.var_name = true; \
|
||||||
}
|
}
|
||||||
#define FEATURE_EXTENSION(prefix, struct_name, macro_name, var_name) \
|
#define FEATURE_EXTENSION(prefix, struct_name, macro_name, var_name) \
|
||||||
if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \
|
if (supported_extensions.contains(VK_##prefix##_##macro_name##_EXTENSION_NAME)) { \
|
||||||
loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \
|
loaded_extensions.insert(VK_##prefix##_##macro_name##_EXTENSION_NAME); \
|
||||||
extensions.var_name = true; \
|
extensions.var_name = true; \
|
||||||
}
|
}
|
||||||
|
|
||||||
if (instance_version < VK_API_VERSION_1_2) {
|
if (instance_version < VK_API_VERSION_1_2) {
|
||||||
@@ -962,19 +1010,24 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
|||||||
extensions.robustness_2 = false;
|
extensions.robustness_2 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// different namings
|
||||||
|
if (supported_extensions.contains(VK_EXT_DEVICE_FAULT_EXTENSION_NAME)) {
|
||||||
|
loaded_extensions.insert(VK_EXT_DEVICE_FAULT_EXTENSION_NAME);
|
||||||
|
extensions.device_fault = true;
|
||||||
|
}
|
||||||
#undef FEATURE_EXTENSION
|
#undef FEATURE_EXTENSION
|
||||||
#undef EXTENSION
|
#undef EXTENSION
|
||||||
|
|
||||||
// Some extensions are mandatory. Check those.
|
// Some extensions are mandatory. Check those.
|
||||||
#define CHECK_EXTENSION(extension_name) \
|
#define CHECK_EXTENSION(extension_name) \
|
||||||
if (!loaded_extensions.contains(extension_name)) { \
|
if (!loaded_extensions.contains(extension_name)) { \
|
||||||
LOG_ERROR(Render_Vulkan, "Missing required extension {}", extension_name); \
|
LOG_ERROR(Render_Vulkan, "Missing required extension {}", extension_name); \
|
||||||
suitable = false; \
|
suitable = false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOG_EXTENSION(extension_name) \
|
#define LOG_EXTENSION(extension_name) \
|
||||||
if (!loaded_extensions.contains(extension_name)) { \
|
if (!loaded_extensions.contains(extension_name)) { \
|
||||||
LOG_INFO(Render_Vulkan, "Device doesn't support extension {}", extension_name); \
|
LOG_INFO(Render_Vulkan, "Device doesn't support extension {}", extension_name); \
|
||||||
}
|
}
|
||||||
|
|
||||||
FOR_EACH_VK_RECOMMENDED_EXTENSION(LOG_EXTENSION);
|
FOR_EACH_VK_RECOMMENDED_EXTENSION(LOG_EXTENSION);
|
||||||
@@ -1016,9 +1069,9 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
|||||||
|
|
||||||
#define EXT_FEATURE(prefix, struct_name, macro_name, var_name) \
|
#define EXT_FEATURE(prefix, struct_name, macro_name, var_name) \
|
||||||
if (extensions.var_name) { \
|
if (extensions.var_name) { \
|
||||||
features.var_name.sType = \
|
features.var_name.sType = \
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_##macro_name##_FEATURES_##prefix; \
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_##macro_name##_FEATURES_##prefix; \
|
||||||
SetNext(next, features.var_name); \
|
SetNext(next, features.var_name); \
|
||||||
}
|
}
|
||||||
|
|
||||||
FOR_EACH_VK_FEATURE_1_1(FEATURE);
|
FOR_EACH_VK_FEATURE_1_1(FEATURE);
|
||||||
@@ -1033,7 +1086,10 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
|||||||
} else {
|
} else {
|
||||||
FOR_EACH_VK_FEATURE_1_3(EXT_FEATURE);
|
FOR_EACH_VK_FEATURE_1_3(EXT_FEATURE);
|
||||||
}
|
}
|
||||||
|
if (extensions.device_fault) {
|
||||||
|
features.device_fault.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FAULT_FEATURES_EXT;
|
||||||
|
SetNext(next, features.device_fault);
|
||||||
|
}
|
||||||
#undef EXT_FEATURE
|
#undef EXT_FEATURE
|
||||||
#undef FEATURE
|
#undef FEATURE
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
#include "video_core/vulkan_common/vulkan_wrapper.h"
|
||||||
|
#include "vulkan/vulkan_core.h"
|
||||||
|
|
||||||
VK_DEFINE_HANDLE(VmaAllocator)
|
VK_DEFINE_HANDLE(VmaAllocator)
|
||||||
|
|
||||||
@@ -93,8 +94,12 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
|||||||
EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \
|
EXTENSION(EXT, SHADER_VIEWPORT_INDEX_LAYER, shader_viewport_index_layer) \
|
||||||
EXTENSION(EXT, TOOLING_INFO, tooling_info) \
|
EXTENSION(EXT, TOOLING_INFO, tooling_info) \
|
||||||
EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \
|
EXTENSION(EXT, VERTEX_ATTRIBUTE_DIVISOR, vertex_attribute_divisor) \
|
||||||
|
<<<<<<< HEAD
|
||||||
EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \
|
EXTENSION(KHR, CREATE_RENDERPASS_2, create_renderpass2) \
|
||||||
EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \
|
EXTENSION(KHR, DEPTH_STENCIL_RESOLVE, depth_stencil_resolve) \
|
||||||
|
EXTENSION(EXT, DEVICE_FAULT, device_fault) \
|
||||||
|
=======
|
||||||
|
>>>>>>> 6e75e5837b (oops, fixup)
|
||||||
EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \
|
EXTENSION(KHR, DRAW_INDIRECT_COUNT, draw_indirect_count) \
|
||||||
EXTENSION(KHR, DRIVER_PROPERTIES, driver_properties) \
|
EXTENSION(KHR, DRIVER_PROPERTIES, driver_properties) \
|
||||||
EXTENSION(KHR, PUSH_DESCRIPTOR, push_descriptor) \
|
EXTENSION(KHR, PUSH_DESCRIPTOR, push_descriptor) \
|
||||||
@@ -1142,33 +1147,28 @@ private:
|
|||||||
struct Extensions {
|
struct Extensions {
|
||||||
#define EXTENSION(prefix, macro_name, var_name) bool var_name{};
|
#define EXTENSION(prefix, macro_name, var_name) bool var_name{};
|
||||||
#define FEATURE(prefix, struct_name, macro_name, var_name) bool var_name{};
|
#define FEATURE(prefix, struct_name, macro_name, var_name) bool var_name{};
|
||||||
|
|
||||||
FOR_EACH_VK_FEATURE_1_1(FEATURE);
|
FOR_EACH_VK_FEATURE_1_1(FEATURE);
|
||||||
FOR_EACH_VK_FEATURE_1_2(FEATURE);
|
FOR_EACH_VK_FEATURE_1_2(FEATURE);
|
||||||
FOR_EACH_VK_FEATURE_1_3(FEATURE);
|
FOR_EACH_VK_FEATURE_1_3(FEATURE);
|
||||||
FOR_EACH_VK_FEATURE_1_4(FEATURE);
|
FOR_EACH_VK_FEATURE_1_4(FEATURE);
|
||||||
FOR_EACH_VK_FEATURE_EXT(FEATURE);
|
FOR_EACH_VK_FEATURE_EXT(FEATURE);
|
||||||
FOR_EACH_VK_EXTENSION(EXTENSION);
|
FOR_EACH_VK_EXTENSION(EXTENSION);
|
||||||
|
|
||||||
#undef EXTENSION
|
#undef EXTENSION
|
||||||
#undef FEATURE
|
#undef FEATURE
|
||||||
|
bool device_fault;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Features {
|
struct Features {
|
||||||
#define FEATURE_CORE(prefix, struct_name, macro_name, var_name) \
|
#define FEATURE_CORE(prefix, struct_name, macro_name, var_name) VkPhysicalDevice##struct_name##Features var_name{};
|
||||||
VkPhysicalDevice##struct_name##Features var_name{};
|
#define FEATURE_EXT(prefix, struct_name, macro_name, var_name) VkPhysicalDevice##struct_name##Features##prefix var_name{};
|
||||||
#define FEATURE_EXT(prefix, struct_name, macro_name, var_name) \
|
|
||||||
VkPhysicalDevice##struct_name##Features##prefix var_name{};
|
|
||||||
|
|
||||||
FOR_EACH_VK_FEATURE_1_1(FEATURE_CORE);
|
FOR_EACH_VK_FEATURE_1_1(FEATURE_CORE);
|
||||||
FOR_EACH_VK_FEATURE_1_2(FEATURE_CORE);
|
FOR_EACH_VK_FEATURE_1_2(FEATURE_CORE);
|
||||||
FOR_EACH_VK_FEATURE_1_3(FEATURE_CORE);
|
FOR_EACH_VK_FEATURE_1_3(FEATURE_CORE);
|
||||||
FOR_EACH_VK_FEATURE_1_4(FEATURE_CORE);
|
FOR_EACH_VK_FEATURE_1_4(FEATURE_CORE);
|
||||||
FOR_EACH_VK_FEATURE_EXT(FEATURE_EXT);
|
FOR_EACH_VK_FEATURE_EXT(FEATURE_EXT);
|
||||||
|
|
||||||
#undef FEATURE_CORE
|
#undef FEATURE_CORE
|
||||||
#undef FEATURE_EXT
|
#undef FEATURE_EXT
|
||||||
|
VkPhysicalDeviceFaultFeaturesEXT device_fault{};
|
||||||
VkPhysicalDeviceFeatures features{};
|
VkPhysicalDeviceFeatures features{};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1183,7 +1183,7 @@ private:
|
|||||||
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
|
VkPhysicalDeviceMaintenance5PropertiesKHR maintenance5{};
|
||||||
VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve{};
|
VkPhysicalDeviceDepthStencilResolveProperties depth_stencil_resolve{};
|
||||||
VkPhysicalDeviceCustomBorderColorPropertiesEXT custom_border_color{};
|
VkPhysicalDeviceCustomBorderColorPropertiesEXT custom_border_color{};
|
||||||
|
VkPhysicalDeviceFaultFeaturesEXT device_fault{};
|
||||||
VkPhysicalDeviceProperties properties{};
|
VkPhysicalDeviceProperties properties{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -246,6 +246,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
|||||||
X(vkCmdSetDescriptorBufferOffsetsEXT);
|
X(vkCmdSetDescriptorBufferOffsetsEXT);
|
||||||
X(vkWaitForFences);
|
X(vkWaitForFences);
|
||||||
X(vkWaitSemaphores);
|
X(vkWaitSemaphores);
|
||||||
|
X(vkGetDeviceFaultInfoEXT);
|
||||||
|
|
||||||
// Support for timeline semaphores is mandatory in Vulkan 1.2
|
// Support for timeline semaphores is mandatory in Vulkan 1.2
|
||||||
if (!dld.vkGetSemaphoreCounterValue) {
|
if (!dld.vkGetSemaphoreCounterValue) {
|
||||||
|
|||||||
@@ -362,6 +362,7 @@ struct DeviceDispatch : InstanceDispatch {
|
|||||||
PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
|
PFN_vkUpdateDescriptorSets vkUpdateDescriptorSets{};
|
||||||
PFN_vkWaitForFences vkWaitForFences{};
|
PFN_vkWaitForFences vkWaitForFences{};
|
||||||
PFN_vkWaitSemaphores vkWaitSemaphores{};
|
PFN_vkWaitSemaphores vkWaitSemaphores{};
|
||||||
|
PFN_vkGetDeviceFaultInfoEXT vkGetDeviceFaultInfoEXT{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Loads instance agnostic function pointers.
|
/// Loads instance agnostic function pointers.
|
||||||
|
|||||||
Reference in New Issue
Block a user