Compare commits

...
Sign in to create a new pull request.

7 commits

Author SHA1 Message Date
ae61b65b6c
Remove Mali conditional for EDS
Signed-off-by: swurl <swurl@swurl.xyz>
2025-05-08 22:43:18 -04:00
318aeebdf3 descriptor_indexing, VIDS, provoking_vertex
Signed-off-by: swurl <swurl@swurl.xyz>
2025-05-08 22:16:21 +00:00
7938031bcc Fully enable 2025-05-08 22:16:21 +00:00
860d8ab741 vulkan: Enable and log Vulkan 1.4 feature support
- Chain VkPhysicalDeviceVulkan13/14Features into device creation
- Query and enable features via vkGetPhysicalDeviceFeatures2
- Log Vulkan 1.4 dynamicPrimitiveTopologyUnrestricted at runtime
2025-05-08 22:16:21 +00:00
JPikachu
293a1ba8de vulkan: Remove checks disabling push_descriptor
Removed explicit calls to `RemoveExtension` that disabled the
VK_KHR_push_descriptor extension for specific hardware/driver
combinations (Qualcomm, older NVIDIA, specific Intel ANV versions).
2025-05-08 22:16:21 +00:00
e0d96535c3 vulkan: Disable VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT 2025-05-08 22:16:21 +00:00
JPikachu
8bf4acad80 vulkan: Remove checks disabling vertex_input_dynamic_state 2025-05-08 22:16:21 +00:00
9 changed files with 150 additions and 79 deletions

View file

@ -57,13 +57,6 @@ abstract class SettingsItem(
return NativeInput.getStyleIndex(0) != NpadStyleIndex.Handheld
}
if (setting.key == ByteSetting.RENDERER_DYNA_STATE.key) {
// Can't change on Mali GPU's otherwise no game loading for you
if (!GpuDriverHelper.supportsCustomDriverLoading()) {
return false
}
}
// Can't edit settings that aren't saveable in per-game config even if they are switchable
if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
return false

View file

@ -446,11 +446,15 @@ struct Values {
SwitchableSetting<u8, true> dyna_state{linkage,
1,
0,
3,
2,
"dyna_state",
Category::RendererExtensions,
Specialization::Scalar};
SwitchableSetting<bool> dyna_state3{linkage, false, "dyna_state3", Category::RendererExtensions};
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex", Category::RendererExtensions};
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing", Category::RendererExtensions};
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
Category::RendererDebug};

View file

@ -28,6 +28,7 @@ public:
num_descriptors <= device->MaxPushDescriptors();
}
// TODO(crueter): utilize layout binding flags
vk::DescriptorSetLayout CreateDescriptorSetLayout(bool use_push_descriptor) const {
if (bindings.empty()) {
return nullptr;

View file

@ -235,6 +235,7 @@ ConfigureFuncPtr ConfigureFunc(const std::array<vk::ShaderModule, NUM_STAGES>& m
}
} // Anonymous namespace
// TODO(crueter): This is the worst-formatted code I have EVER seen
GraphicsPipeline::GraphicsPipeline(
Scheduler& scheduler_, BufferCache& buffer_cache_, TextureCache& texture_cache_,
vk::PipelineCache& pipeline_cache_, VideoCore::ShaderNotify* shader_notify,
@ -263,9 +264,11 @@ GraphicsPipeline::GraphicsPipeline(
DescriptorLayoutBuilder builder{MakeBuilder(device, stage_infos)};
uses_push_descriptor = builder.CanUsePushDescriptor();
descriptor_set_layout = builder.CreateDescriptorSetLayout(uses_push_descriptor);
if (!uses_push_descriptor) {
descriptor_allocator = descriptor_pool.Allocator(*descriptor_set_layout, stage_infos);
}
const VkDescriptorSetLayout set_layout{*descriptor_set_layout};
pipeline_layout = builder.CreatePipelineLayout(set_layout);
descriptor_update_template =
@ -716,13 +719,14 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
};
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
line_state.pNext = std::exchange(rasterization_ci.pNext, &line_state);
}
if (device.IsExtConservativeRasterizationSupported()) {
conservative_raster.pNext = std::exchange(rasterization_ci.pNext, &conservative_raster);
}
if (device.IsExtProvokingVertexSupported()) {
if (device.IsExtProvokingVertexSupported() && Settings::values.provoking_vertex.GetValue()) {
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
}
@ -803,7 +807,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
static constexpr std::array extended{
VK_DYNAMIC_STATE_CULL_MODE_EXT,
VK_DYNAMIC_STATE_FRONT_FACE_EXT,
VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
//VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT, //Disabled for VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME
VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
@ -897,6 +901,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
if (device.IsKhrPipelineExecutablePropertiesEnabled()) {
flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
}
pipeline = device.GetLogical().CreateGraphicsPipeline(
{
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,

View file

@ -403,20 +403,23 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
}
const u8 dynamic_state = Settings::values.dyna_state.GetValue();
const bool dynamic_state3 = dynamic_state == 2 && Settings::values.dyna_state3.GetValue();
LOG_INFO(Render_Vulkan, "DynamicState value is set to {}", (u32) dynamic_state);
LOG_INFO(Render_Vulkan, "DynamicState3 value is set to {}", dynamic_state3);
dynamic_features = DynamicFeatures{
.has_extended_dynamic_state = device.IsExtExtendedDynamicStateSupported() && dynamic_state > 0,
.has_extended_dynamic_state_2 = device.IsExtExtendedDynamicState2Supported() && dynamic_state > 1,
.has_extended_dynamic_state_2_extra = device.IsExtExtendedDynamicState2ExtrasSupported() && dynamic_state > 1,
.has_extended_dynamic_state_3_blend = device.IsExtExtendedDynamicState3BlendingSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported() && dynamic_state > 2,
.has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported(),
.has_extended_dynamic_state_3_blend = device.IsExtExtendedDynamicState3BlendingSupported() && dynamic_state3,
.has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported() && dynamic_state3,
.has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported(),// && dynamic_state3,
};
LOG_INFO(Render_Vulkan, "DynamicState1: {}", dynamic_features.has_extended_dynamic_state);
LOG_INFO(Render_Vulkan, "DynamicState2: {}", dynamic_features.has_extended_dynamic_state_2);
LOG_INFO(Render_Vulkan, "DynamicState3: {}", dynamic_features.has_extended_dynamic_state_3_enables);
LOG_INFO(Render_Vulkan, "DynamicVertexInput: {}", dynamic_features.has_dynamic_vertex_input);
}
PipelineCache::~PipelineCache() {

View file

@ -314,17 +314,17 @@ void OverrideBcnFormats(std::unordered_map<VkFormat, VkFormatProperties>& format
NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
const std::set<std::string, std::less<>>& exts) {
VkPhysicalDeviceProperties2 physical_properties{};
physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physical_properties.pNext = nullptr;
if (exts.contains(VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME)) {
VkPhysicalDeviceFragmentShadingRatePropertiesKHR shading_rate_props{};
shading_rate_props.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
VkPhysicalDeviceProperties2 physical_properties{};
physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physical_properties.pNext = &shading_rate_props;
physical.GetProperties2(physical_properties);
if (shading_rate_props.primitiveFragmentShadingRateWithMultipleViewports) {
// Only Ampere and newer support this feature
// TODO: Find a way to differentiate Ampere and Ada
return NvidiaArchitecture::Arch_AmpereOrNewer;
}
return NvidiaArchitecture::Arch_Turing;
@ -334,8 +334,6 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT advanced_blending_props{};
advanced_blending_props.sType =
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
VkPhysicalDeviceProperties2 physical_properties{};
physical_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
physical_properties.pNext = &advanced_blending_props;
physical.GetProperties2(physical_properties);
if (advanced_blending_props.advancedBlendMaxColorAttachments == 1) {
@ -447,7 +445,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
const void* first_next = &features2;
VkDeviceDiagnosticsConfigCreateInfoNV diagnostics_nv{};
if (Settings::values.enable_nsight_aftermath && extensions.device_diagnostics_config) {
const bool use_diagnostics_nv = Settings::values.enable_nsight_aftermath && extensions.device_diagnostics_config;
if (use_diagnostics_nv) {
nsight_aftermath_tracker = std::make_unique<NsightAftermathTracker>();
diagnostics_nv = {
@ -460,6 +459,18 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
first_next = &diagnostics_nv;
}
VkPhysicalDeviceDescriptorIndexingFeaturesEXT descriptor_indexing{
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT,
.pNext = use_diagnostics_nv ? static_cast<void*>(&diagnostics_nv) : static_cast<void*>(&features2),
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
.descriptorBindingPartiallyBound = VK_TRUE,
.descriptorBindingVariableDescriptorCount = VK_TRUE,
};
if (extensions.descriptor_indexing && Settings::values.descriptor_indexing.GetValue()) {
first_next = &descriptor_indexing;
}
is_blit_depth24_stencil8_supported = TestDepthStencilBlits(VK_FORMAT_D24_UNORM_S8_UINT);
is_blit_depth32_stencil8_supported = TestDepthStencilBlits(VK_FORMAT_D32_SFLOAT_S8_UINT);
is_optimal_astc_supported = ComputeIsOptimalAstcSupported();
@ -490,7 +501,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
if (is_qualcomm) {
LOG_WARNING(Render_Vulkan,
"Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
// Patch the driver to enable BCn textures.
@ -524,7 +535,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
} else if (arch <= NvidiaArchitecture::Arch_Volta) {
if (nv_major_version < 527) {
LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
}
}
if (nv_major_version >= 510) {
@ -641,9 +652,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
const u32 version = (properties.properties.driverVersion << 3) >> 3;
if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state");
RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
features.vertex_input_dynamic_state,
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
//RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
//features.vertex_input_dynamic_state,
//VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
}
}
if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) {
@ -670,14 +681,14 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
// mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc
LOG_WARNING(Render_Vulkan,
"ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor");
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
}
} else if (extensions.push_descriptor && is_nvidia) {
const auto arch = GetNvidiaArch();
if (arch <= NvidiaArchitecture::Arch_Pascal) {
LOG_WARNING(Render_Vulkan,
"Pascal and older architectures have broken VK_KHR_push_descriptor");
RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
//RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
}
}
@ -725,8 +736,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2,
VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
RemoveExtensionFeature(extensions.vertex_input_dynamic_state, features.vertex_input_dynamic_state,
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
//RemoveExtensionFeature(extensions.vertex_input_dynamic_state, features.vertex_input_dynamic_state,
//VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
// Disable extended dynamic state 3 features
features.extended_dynamic_state3.extendedDynamicState3ColorBlendEnable = false;
@ -963,6 +974,11 @@ bool Device::GetSuitability(bool requires_swapchain) {
// Assume we will be suitable.
bool suitable = true;
// Configure properties.
VkPhysicalDeviceVulkan12Features features_1_2{};
VkPhysicalDeviceVulkan13Features features_1_3{};
VkPhysicalDeviceVulkan14Features features_1_4{};
// Configure properties.
properties.properties = physical.GetProperties();
@ -1036,6 +1052,19 @@ bool Device::GetSuitability(bool requires_swapchain) {
// Set next pointer.
void** next = &features2.pNext;
// Vulkan 1.2, 1.3 and 1.4 features
if (instance_version >= VK_API_VERSION_1_2) {
features_1_2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
features_1_3.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
features_1_4.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_FEATURES;
features_1_2.pNext = &features_1_3;
features_1_3.pNext = &features_1_4;
*next = &features_1_2;
// next = &features_1_4.pNext;
}
// Test all features we know about. If the feature is not available in core at our
// current API version, and was not enabled by an extension, skip testing the feature.
// We set the structure sType explicitly here as it is zeroed by the constructor.
@ -1068,6 +1097,8 @@ bool Device::GetSuitability(bool requires_swapchain) {
// Perform the feature test.
physical.GetFeatures2(features2);
// Base Vulkan 1.0 features are always valid regardless of instance version.
features.features = features2.features;
// Some features are mandatory. Check those.
@ -1126,6 +1157,8 @@ bool Device::GetSuitability(bool requires_swapchain) {
// Perform the property fetch.
physical.GetProperties2(properties2);
// Store base properties
properties.properties = properties2.properties;
// Unload extensions if feature support is insufficient.
@ -1208,8 +1241,8 @@ void Device::RemoveUnsuitableExtensions() {
extensions.provoking_vertex =
features.provoking_vertex.provokingVertexLast &&
features.provoking_vertex.transformFeedbackPreservesProvokingVertex;
RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex, features.provoking_vertex,
VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
// RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex, features.provoking_vertex,
// VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
// VK_KHR_shader_atomic_int64
extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics &&
@ -1247,9 +1280,9 @@ void Device::RemoveUnsuitableExtensions() {
// VK_EXT_vertex_input_dynamic_state
extensions.vertex_input_dynamic_state =
features.vertex_input_dynamic_state.vertexInputDynamicState;
RemoveExtensionFeatureIfUnsuitable(extensions.vertex_input_dynamic_state,
features.vertex_input_dynamic_state,
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
//RemoveExtensionFeatureIfUnsuitable(extensions.vertex_input_dynamic_state,
//features.vertex_input_dynamic_state,
//VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
// VK_KHR_pipeline_executable_properties
if (Settings::values.renderer_shader_feedback.GetValue()) {

View file

@ -84,7 +84,8 @@ VK_DEFINE_HANDLE(VmaAllocator)
EXTENSION(NV, DEVICE_DIAGNOSTICS_CONFIG, device_diagnostics_config) \
EXTENSION(NV, GEOMETRY_SHADER_PASSTHROUGH, geometry_shader_passthrough) \
EXTENSION(NV, VIEWPORT_ARRAY2, viewport_array2) \
EXTENSION(NV, VIEWPORT_SWIZZLE, viewport_swizzle)
EXTENSION(NV, VIEWPORT_SWIZZLE, viewport_swizzle) \
EXTENSION(EXT, DESCRIPTOR_INDEXING, descriptor_indexing)
// Define extensions which must be supported.
#define FOR_EACH_VK_MANDATORY_EXTENSION(EXTENSION_NAME) \
@ -404,6 +405,11 @@ public:
return extensions.viewport_array2;
}
/// Returns true if the device supporst VK_EXT_DESCRIPTOR_INDEXING
bool isExtDescriptorIndexingSupported() const {
return extensions.descriptor_indexing;
}
/// Returns true if the device supports VK_NV_geometry_shader_passthrough.
bool IsNvGeometryShaderPassthroughSupported() const {
return extensions.geometry_shader_passthrough;

View file

@ -33,6 +33,9 @@ void ConfigureGraphicsExtensions::SetConfiguration() {}
void ConfigureGraphicsExtensions::Setup(const ConfigurationShared::Builder& builder) {
auto& layout = *ui->populate_target->layout();
std::map<u32, QWidget*> hold{}; // A map will sort the data for us
QSlider *dyna_state = nullptr;
QCheckBox *dyna_state3 = nullptr;
for (auto setting :
Settings::values.linkage.by_category[Settings::Category::RendererExtensions]) {
ConfigurationShared::Widget* widget = builder.BuildWidget(setting, apply_funcs);
@ -50,12 +53,22 @@ void ConfigureGraphicsExtensions::Setup(const ConfigurationShared::Builder& buil
if (setting->Id() == Settings::values.dyna_state.Id()) {
widget->slider->setTickInterval(1);
widget->slider->setTickPosition(QSlider::TicksAbove);
dyna_state = widget->slider;
} else if (setting->Id() == Settings::values.dyna_state3.Id()) {
dyna_state3 = widget->checkbox;
}
}
for (const auto& [id, widget] : hold) {
layout.addWidget(widget);
}
connect(dyna_state, &QSlider::sliderMoved, this, [dyna_state3](int value) {
dyna_state3->setEnabled(value == 2);
if (value < 2) {
dyna_state3->setChecked(false);
}
});
}
void ConfigureGraphicsExtensions::ApplyConfiguration() {

View file

@ -235,6 +235,19 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
tr("Enables the VkExtendedDynamicState* extensions.\nHigher dynamic states will generally improve "
"performance, but may cause issues on certain games or devices."));
INSERT(Settings, dyna_state3, tr("EDS3 + Vertex Input"),
tr("Enables the VkExtendedDynamicState3 and VkVertexInputDynamicState extensions.\n"
"Only Vulkan 1.3+ devices support these extensions, and will generally see improved performance,\n"
"though certain games such as Breath of the Wild may see issues with this setting."));
INSERT(Settings, provoking_vertex, tr("Provoking Vertex"),
tr("Improves lighting and vertex handling in certain games.\n"
"Only Vulkan 1.0+ devices support this extension, notably excluding pre-Valhal ARM GPUs."));
INSERT(Settings, descriptor_indexing, tr("Descriptor Indexing"),
tr("Improves texture & buffer handling and the Maxwell translation layer.\n"
"Some Vulkan 1.1+ and all 1.2+ devices support this extension."));
// Renderer (Debug)
// System