Compare commits

..

7 Commits

Author SHA1 Message Date
lizzie b71ddb302a sds 2026-08-29 06:29:31 +00:00
lizzie 00243891d1 oops, fixup 2026-08-29 06:29:31 +00:00
lizzie 5d42bfba0d fx 2026-08-29 06:29:05 +00:00
lizzie 42db87998f fix device fault? 2026-08-29 06:29:05 +00:00
lizzie 9a8477eb43 fix logged 2026-08-29 06:28:26 +00:00
lizzie 565b04fd12 fx 2026-08-29 06:28:26 +00:00
lizzie 9941453610 [vulkan] support VK_EXT_fault_info when VK_ERROR_DEVICE_LOST is incurred
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-08-29 06:28:26 +00:00
16 changed files with 105 additions and 119 deletions
+8 -24
View File
@@ -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"
@@ -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)
@@ -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)
}
@@ -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,
@@ -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
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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;
} }
+2 -2
View File
@@ -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();
+69 -13
View File
@@ -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
+10 -10
View File
@@ -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.