summaryrefslogtreecommitdiffstats
path: root/src/video_core/vulkan_common
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/vulkan_common')
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.cpp40
-rw-r--r--src/video_core/vulkan_common/vulkan_debug_callback.h4
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp6
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h35
-rw-r--r--src/video_core/vulkan_common/vulkan_instance.cpp58
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.cpp14
-rw-r--r--src/video_core/vulkan_common/vulkan_wrapper.h9
7 files changed, 126 insertions, 40 deletions
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.cpp b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
index 9de484c29..67e8065a4 100644
--- a/src/video_core/vulkan_common/vulkan_debug_callback.cpp
+++ b/src/video_core/vulkan_common/vulkan_debug_callback.cpp
@@ -7,10 +7,10 @@
namespace Vulkan {
namespace {
-VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
- VkDebugUtilsMessageTypeFlagsEXT type,
- const VkDebugUtilsMessengerCallbackDataEXT* data,
- [[maybe_unused]] void* user_data) {
+VkBool32 DebugUtilCallback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
+ VkDebugUtilsMessageTypeFlagsEXT type,
+ const VkDebugUtilsMessengerCallbackDataEXT* data,
+ [[maybe_unused]] void* user_data) {
// Skip logging known false-positive validation errors
switch (static_cast<u32>(data->messageIdNumber)) {
#ifdef ANDROID
@@ -62,9 +62,26 @@ VkBool32 Callback(VkDebugUtilsMessageSeverityFlagBitsEXT severity,
}
return VK_FALSE;
}
+
+VkBool32 DebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType,
+ uint64_t object, size_t location, int32_t messageCode,
+ const char* pLayerPrefix, const char* pMessage, void* pUserData) {
+ const VkDebugReportFlagBitsEXT severity = static_cast<VkDebugReportFlagBitsEXT>(flags);
+ const std::string_view message{pMessage};
+ if (severity & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ LOG_CRITICAL(Render_Vulkan, "{}", message);
+ } else if (severity & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ LOG_WARNING(Render_Vulkan, "{}", message);
+ } else if (severity & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) {
+ LOG_INFO(Render_Vulkan, "{}", message);
+ } else if (severity & VK_DEBUG_REPORT_DEBUG_BIT_EXT) {
+ LOG_DEBUG(Render_Vulkan, "{}", message);
+ }
+ return VK_FALSE;
+}
} // Anonymous namespace
-vk::DebugUtilsMessenger CreateDebugCallback(const vk::Instance& instance) {
+vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance) {
return instance.CreateDebugUtilsMessenger(VkDebugUtilsMessengerCreateInfoEXT{
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.pNext = nullptr,
@@ -76,7 +93,18 @@ vk::DebugUtilsMessenger CreateDebugCallback(const vk::Instance& instance) {
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
- .pfnUserCallback = Callback,
+ .pfnUserCallback = DebugUtilCallback,
+ .pUserData = nullptr,
+ });
+}
+
+vk::DebugReportCallback CreateDebugReportCallback(const vk::Instance& instance) {
+ return instance.CreateDebugReportCallback({
+ .sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
+ .pNext = nullptr,
+ .flags = VK_DEBUG_REPORT_DEBUG_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT |
+ VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
+ .pfnCallback = DebugReportCallback,
.pUserData = nullptr,
});
}
diff --git a/src/video_core/vulkan_common/vulkan_debug_callback.h b/src/video_core/vulkan_common/vulkan_debug_callback.h
index 71b1f69ec..a8af7b406 100644
--- a/src/video_core/vulkan_common/vulkan_debug_callback.h
+++ b/src/video_core/vulkan_common/vulkan_debug_callback.h
@@ -7,6 +7,8 @@
namespace Vulkan {
-vk::DebugUtilsMessenger CreateDebugCallback(const vk::Instance& instance);
+vk::DebugUtilsMessenger CreateDebugUtilsCallback(const vk::Instance& instance);
+
+vk::DebugReportCallback CreateDebugReportCallback(const vk::Instance& instance);
} // namespace Vulkan
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index e4ca65b58..70436cf1c 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -349,7 +349,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
const bool is_s8gen2 = device_id == 0x43050a01;
const bool is_arm = driver_id == VK_DRIVER_ID_ARM_PROPRIETARY;
- if ((is_mvk || is_qualcomm || is_turnip) && !is_suitable) {
+ if ((is_mvk || is_qualcomm || is_turnip || is_arm) && !is_suitable) {
LOG_WARNING(Render_Vulkan, "Unsuitable driver, continuing anyway");
} else if (!is_suitable) {
throw vk::Exception(VK_ERROR_INCOMPATIBLE_DRIVER);
@@ -905,6 +905,10 @@ bool Device::GetSuitability(bool requires_swapchain) {
properties.driver.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
SetNext(next, properties.driver);
+ // Retrieve subgroup properties.
+ properties.subgroup_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
+ SetNext(next, properties.subgroup_properties);
+
// Retrieve relevant extension properties.
if (extensions.shader_float_controls) {
properties.float_controls.sType =
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index b84af3dfb..1f17265d5 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -293,6 +293,11 @@ public:
return features.features.textureCompressionASTC_LDR;
}
+ /// Returns true if BCn is natively supported.
+ bool IsOptimalBcnSupported() const {
+ return features.features.textureCompressionBC;
+ }
+
/// Returns true if descriptor aliasing is natively supported.
bool IsDescriptorAliasingSupported() const {
return GetDriverID() != VK_DRIVER_ID_QUALCOMM_PROPRIETARY;
@@ -323,6 +328,11 @@ public:
return properties.subgroup_size_control.requiredSubgroupSizeStages & stage;
}
+ /// Returns true if the device supports the provided subgroup feature.
+ bool IsSubgroupFeatureSupported(VkSubgroupFeatureFlagBits feature) const {
+ return properties.subgroup_properties.supportedOperations & feature;
+ }
+
/// Returns the maximum number of push descriptors.
u32 MaxPushDescriptors() const {
return properties.push_descriptor.maxPushDescriptors;
@@ -388,6 +398,11 @@ public:
return extensions.swapchain_mutable_format;
}
+ /// Returns true if VK_KHR_shader_float_controls is enabled.
+ bool IsKhrShaderFloatControlsSupported() const {
+ return extensions.shader_float_controls;
+ }
+
/// Returns true if the device supports VK_KHR_workgroup_memory_explicit_layout.
bool IsKhrWorkgroupMemoryExplicitLayoutSupported() const {
return extensions.workgroup_memory_explicit_layout;
@@ -413,6 +428,11 @@ public:
return extensions.sampler_filter_minmax;
}
+ /// Returns true if the device supports VK_EXT_shader_stencil_export.
+ bool IsExtShaderStencilExportSupported() const {
+ return extensions.shader_stencil_export;
+ }
+
/// Returns true if the device supports VK_EXT_depth_range_unrestricted.
bool IsExtDepthRangeUnrestrictedSupported() const {
return extensions.depth_range_unrestricted;
@@ -482,9 +502,9 @@ public:
return extensions.vertex_input_dynamic_state;
}
- /// Returns true if the device supports VK_EXT_shader_stencil_export.
- bool IsExtShaderStencilExportSupported() const {
- return extensions.shader_stencil_export;
+ /// Returns true if the device supports VK_EXT_shader_demote_to_helper_invocation
+ bool IsExtShaderDemoteToHelperInvocationSupported() const {
+ return extensions.shader_demote_to_helper_invocation;
}
/// Returns true if the device supports VK_EXT_conservative_rasterization.
@@ -518,12 +538,12 @@ public:
if (extensions.spirv_1_4) {
return 0x00010400U;
}
- return 0x00010000U;
+ return 0x00010300U;
}
/// Returns true when a known debugging tool is attached.
bool HasDebuggingToolAttached() const {
- return has_renderdoc || has_nsight_graphics || Settings::values.renderer_debug.GetValue();
+ return has_renderdoc || has_nsight_graphics;
}
/// @returns True if compute pipelines can cause crashing.
@@ -588,6 +608,10 @@ public:
return properties.properties.limits.maxVertexInputBindings;
}
+ u32 GetMaxViewports() const {
+ return properties.properties.limits.maxViewports;
+ }
+
bool SupportsConditionalBarriers() const {
return supports_conditional_barriers;
}
@@ -680,6 +704,7 @@ private:
struct Properties {
VkPhysicalDeviceDriverProperties driver{};
+ VkPhysicalDeviceSubgroupProperties subgroup_properties{};
VkPhysicalDeviceFloatControlsProperties float_controls{};
VkPhysicalDevicePushDescriptorPropertiesKHR push_descriptor{};
VkPhysicalDeviceSubgroupSizeControlProperties subgroup_size_control{};
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp
index b6d83e446..7624a9b32 100644
--- a/src/video_core/vulkan_common/vulkan_instance.cpp
+++ b/src/video_core/vulkan_common/vulkan_instance.cpp
@@ -31,10 +31,34 @@
namespace Vulkan {
namespace {
+
+[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld,
+ std::span<const char* const> extensions) {
+ const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld);
+ if (!properties) {
+ LOG_ERROR(Render_Vulkan, "Failed to query extension properties");
+ return false;
+ }
+ for (const char* extension : extensions) {
+ const auto it = std::ranges::find_if(*properties, [extension](const auto& prop) {
+ return std::strcmp(extension, prop.extensionName) == 0;
+ });
+ if (it == properties->end()) {
+ LOG_ERROR(Render_Vulkan, "Required instance extension {} is not available", extension);
+ return false;
+ }
+ }
+ return true;
+}
+
[[nodiscard]] std::vector<const char*> RequiredExtensions(
- Core::Frontend::WindowSystemType window_type, bool enable_validation) {
+ const vk::InstanceDispatch& dld, Core::Frontend::WindowSystemType window_type,
+ bool enable_validation) {
std::vector<const char*> extensions;
extensions.reserve(6);
+#ifdef __APPLE__
+ extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
+#endif
switch (window_type) {
case Core::Frontend::WindowSystemType::Headless:
break;
@@ -66,35 +90,14 @@ namespace {
extensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
}
if (enable_validation) {
- extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
+ const bool debug_utils =
+ AreExtensionsSupported(dld, std::array{VK_EXT_DEBUG_UTILS_EXTENSION_NAME});
+ extensions.push_back(debug_utils ? VK_EXT_DEBUG_UTILS_EXTENSION_NAME
+ : VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
}
- extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
-
-#ifdef __APPLE__
- extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
-#endif
return extensions;
}
-[[nodiscard]] bool AreExtensionsSupported(const vk::InstanceDispatch& dld,
- std::span<const char* const> extensions) {
- const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld);
- if (!properties) {
- LOG_ERROR(Render_Vulkan, "Failed to query extension properties");
- return false;
- }
- for (const char* extension : extensions) {
- const auto it = std::ranges::find_if(*properties, [extension](const auto& prop) {
- return std::strcmp(extension, prop.extensionName) == 0;
- });
- if (it == properties->end()) {
- LOG_ERROR(Render_Vulkan, "Required instance extension {} is not available", extension);
- return false;
- }
- }
- return true;
-}
-
[[nodiscard]] std::vector<const char*> Layers(bool enable_validation) {
std::vector<const char*> layers;
if (enable_validation) {
@@ -138,7 +141,8 @@ vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceD
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan function pointers");
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
- const std::vector<const char*> extensions = RequiredExtensions(window_type, enable_validation);
+ const std::vector<const char*> extensions =
+ RequiredExtensions(dld, window_type, enable_validation);
if (!AreExtensionsSupported(dld, extensions)) {
throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT);
}
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp
index 28fcb21a0..2fa29793a 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.cpp
+++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp
@@ -259,7 +259,9 @@ bool Load(VkInstance instance, InstanceDispatch& dld) noexcept {
// These functions may fail to load depending on the enabled extensions.
// Don't return a failure on these.
X(vkCreateDebugUtilsMessengerEXT);
+ X(vkCreateDebugReportCallbackEXT);
X(vkDestroyDebugUtilsMessengerEXT);
+ X(vkDestroyDebugReportCallbackEXT);
X(vkDestroySurfaceKHR);
X(vkGetPhysicalDeviceFeatures2);
X(vkGetPhysicalDeviceProperties2);
@@ -481,6 +483,11 @@ void Destroy(VkInstance instance, VkDebugUtilsMessengerEXT handle,
dld.vkDestroyDebugUtilsMessengerEXT(instance, handle, nullptr);
}
+void Destroy(VkInstance instance, VkDebugReportCallbackEXT handle,
+ const InstanceDispatch& dld) noexcept {
+ dld.vkDestroyDebugReportCallbackEXT(instance, handle, nullptr);
+}
+
void Destroy(VkInstance instance, VkSurfaceKHR handle, const InstanceDispatch& dld) noexcept {
dld.vkDestroySurfaceKHR(instance, handle, nullptr);
}
@@ -549,6 +556,13 @@ DebugUtilsMessenger Instance::CreateDebugUtilsMessenger(
return DebugUtilsMessenger(object, handle, *dld);
}
+DebugReportCallback Instance::CreateDebugReportCallback(
+ const VkDebugReportCallbackCreateInfoEXT& create_info) const {
+ VkDebugReportCallbackEXT object;
+ Check(dld->vkCreateDebugReportCallbackEXT(handle, &create_info, nullptr, &object));
+ return DebugReportCallback(object, handle, *dld);
+}
+
void Image::SetObjectNameEXT(const char* name) const {
SetObjectName(dld, owner, handle, VK_OBJECT_TYPE_IMAGE, name);
}
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.h b/src/video_core/vulkan_common/vulkan_wrapper.h
index 44fce47a5..b5e70fcd4 100644
--- a/src/video_core/vulkan_common/vulkan_wrapper.h
+++ b/src/video_core/vulkan_common/vulkan_wrapper.h
@@ -164,8 +164,10 @@ struct InstanceDispatch {
PFN_vkEnumerateInstanceLayerProperties vkEnumerateInstanceLayerProperties{};
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT{};
+ PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT{};
PFN_vkCreateDevice vkCreateDevice{};
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT{};
+ PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT{};
PFN_vkDestroyDevice vkDestroyDevice{};
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR{};
PFN_vkEnumerateDeviceExtensionProperties vkEnumerateDeviceExtensionProperties{};
@@ -366,6 +368,7 @@ void Destroy(VkDevice, VkSwapchainKHR, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkSemaphore, const DeviceDispatch&) noexcept;
void Destroy(VkDevice, VkShaderModule, const DeviceDispatch&) noexcept;
void Destroy(VkInstance, VkDebugUtilsMessengerEXT, const InstanceDispatch&) noexcept;
+void Destroy(VkInstance, VkDebugReportCallbackEXT, const InstanceDispatch&) noexcept;
void Destroy(VkInstance, VkSurfaceKHR, const InstanceDispatch&) noexcept;
VkResult Free(VkDevice, VkDescriptorPool, Span<VkDescriptorSet>, const DeviceDispatch&) noexcept;
@@ -581,6 +584,7 @@ private:
};
using DebugUtilsMessenger = Handle<VkDebugUtilsMessengerEXT, VkInstance, InstanceDispatch>;
+using DebugReportCallback = Handle<VkDebugReportCallbackEXT, VkInstance, InstanceDispatch>;
using DescriptorSetLayout = Handle<VkDescriptorSetLayout, VkDevice, DeviceDispatch>;
using DescriptorUpdateTemplate = Handle<VkDescriptorUpdateTemplate, VkDevice, DeviceDispatch>;
using Pipeline = Handle<VkPipeline, VkDevice, DeviceDispatch>;
@@ -613,6 +617,11 @@ public:
DebugUtilsMessenger CreateDebugUtilsMessenger(
const VkDebugUtilsMessengerCreateInfoEXT& create_info) const;
+ /// Creates a debug report callback.
+ /// @throw Exception on creation failure.
+ DebugReportCallback CreateDebugReportCallback(
+ const VkDebugReportCallbackCreateInfoEXT& create_info) const;
+
/// Returns dispatch table.
const InstanceDispatch& Dispatch() const noexcept {
return *dld;