summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp179
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h9
2 files changed, 114 insertions, 74 deletions
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 710929ac5..adde96aa5 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -326,6 +326,43 @@ std::vector<const char*> ExtensionListForVulkan(
326 326
327} // Anonymous namespace 327} // Anonymous namespace
328 328
329void Device::RemoveExtension(bool& extension, const std::string& extension_name) {
330 extension = false;
331 loaded_extensions.erase(extension_name);
332}
333
334void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) {
335 if (loaded_extensions.contains(extension_name) && !is_suitable) {
336 LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name);
337 this->RemoveExtension(is_suitable, extension_name);
338 }
339}
340
341template <typename Feature>
342void Device::RemoveExtensionFeature(bool& extension, Feature& feature,
343 const std::string& extension_name) {
344 // Unload extension.
345 this->RemoveExtension(extension, extension_name);
346
347 // Save sType and pNext for chain.
348 VkStructureType sType = feature.sType;
349 void* pNext = feature.pNext;
350
351 // Clear feature struct and restore chain.
352 feature = {};
353 feature.sType = sType;
354 feature.pNext = pNext;
355}
356
357template <typename Feature>
358void Device::RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature,
359 const std::string& extension_name) {
360 if (loaded_extensions.contains(extension_name) && !is_suitable) {
361 LOG_WARNING(Render_Vulkan, "Removing features for unsuitable extension {}", extension_name);
362 this->RemoveExtensionFeature(is_suitable, feature, extension_name);
363 }
364}
365
329Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface, 366Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface,
330 const vk::InstanceDispatch& dld_) 367 const vk::InstanceDispatch& dld_)
331 : instance{instance_}, dld{dld_}, physical{physical_}, 368 : instance{instance_}, dld{dld_}, physical{physical_},
@@ -397,21 +434,20 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
397 if (is_qualcomm || is_turnip) { 434 if (is_qualcomm || is_turnip) {
398 LOG_WARNING(Render_Vulkan, 435 LOG_WARNING(Render_Vulkan,
399 "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color"); 436 "Qualcomm and Turnip drivers have broken VK_EXT_custom_border_color");
400 extensions.custom_border_color = false; 437 RemoveExtensionFeature(extensions.custom_border_color, features.custom_border_color,
401 loaded_extensions.erase(VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); 438 VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
402 } 439 }
403 440
404 if (is_qualcomm) { 441 if (is_qualcomm) {
405 must_emulate_scaled_formats = true; 442 must_emulate_scaled_formats = true;
406 443
407 LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state"); 444 LOG_WARNING(Render_Vulkan, "Qualcomm drivers have broken VK_EXT_extended_dynamic_state");
408 extensions.extended_dynamic_state = false; 445 RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
409 loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); 446 VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
410 447
411 LOG_WARNING(Render_Vulkan, 448 LOG_WARNING(Render_Vulkan,
412 "Qualcomm drivers have a slow VK_KHR_push_descriptor implementation"); 449 "Qualcomm drivers have a slow VK_KHR_push_descriptor implementation");
413 extensions.push_descriptor = false; 450 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
414 loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
415 451
416#if defined(ANDROID) && defined(ARCHITECTURE_arm64) 452#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
417 // Patch the driver to enable BCn textures. 453 // Patch the driver to enable BCn textures.
@@ -440,15 +476,12 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
440 must_emulate_scaled_formats = true; 476 must_emulate_scaled_formats = true;
441 477
442 LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state"); 478 LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state");
443 extensions.extended_dynamic_state = false; 479 RemoveExtensionFeature(extensions.extended_dynamic_state, features.extended_dynamic_state,
444 loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); 480 VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
445 481
446 LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2"); 482 LOG_WARNING(Render_Vulkan, "ARM drivers have broken VK_EXT_extended_dynamic_state2");
447 features.extended_dynamic_state2.extendedDynamicState2 = false; 483 RemoveExtensionFeature(extensions.extended_dynamic_state2, features.extended_dynamic_state2,
448 features.extended_dynamic_state2.extendedDynamicState2LogicOp = false; 484 VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
449 features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false;
450 extensions.extended_dynamic_state2 = false;
451 loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
452 } 485 }
453 486
454 if (is_nvidia) { 487 if (is_nvidia) {
@@ -464,8 +497,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
464 case NvidiaArchitecture::VoltaOrOlder: 497 case NvidiaArchitecture::VoltaOrOlder:
465 if (nv_major_version < 527) { 498 if (nv_major_version < 527) {
466 LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor"); 499 LOG_WARNING(Render_Vulkan, "Volta and older have broken VK_KHR_push_descriptor");
467 extensions.push_descriptor = false; 500 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
468 loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
469 } 501 }
470 break; 502 break;
471 } 503 }
@@ -480,8 +512,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
480 if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) { 512 if (version < VK_MAKE_API_VERSION(0, 21, 2, 0)) {
481 LOG_WARNING(Render_Vulkan, 513 LOG_WARNING(Render_Vulkan,
482 "RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state"); 514 "RADV versions older than 21.2 have broken VK_EXT_extended_dynamic_state");
483 extensions.extended_dynamic_state = false; 515 RemoveExtensionFeature(extensions.extended_dynamic_state,
484 loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); 516 features.extended_dynamic_state,
517 VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
485 } 518 }
486 } 519 }
487 if (extensions.extended_dynamic_state2 && is_radv) { 520 if (extensions.extended_dynamic_state2 && is_radv) {
@@ -490,11 +523,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
490 LOG_WARNING( 523 LOG_WARNING(
491 Render_Vulkan, 524 Render_Vulkan,
492 "RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2"); 525 "RADV versions older than 22.3.1 have broken VK_EXT_extended_dynamic_state2");
493 features.extended_dynamic_state2.extendedDynamicState2 = false; 526 RemoveExtensionFeature(extensions.extended_dynamic_state2,
494 features.extended_dynamic_state2.extendedDynamicState2LogicOp = false; 527 features.extended_dynamic_state2,
495 features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false; 528 VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
496 extensions.extended_dynamic_state2 = false;
497 loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
498 } 529 }
499 } 530 }
500 if (extensions.extended_dynamic_state2 && is_qualcomm) { 531 if (extensions.extended_dynamic_state2 && is_qualcomm) {
@@ -504,11 +535,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
504 // Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2. 535 // Qualcomm Adreno 7xx drivers do not properly support extended_dynamic_state2.
505 LOG_WARNING(Render_Vulkan, 536 LOG_WARNING(Render_Vulkan,
506 "Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2"); 537 "Qualcomm Adreno 7xx drivers have broken VK_EXT_extended_dynamic_state2");
507 features.extended_dynamic_state2.extendedDynamicState2 = false; 538 RemoveExtensionFeature(extensions.extended_dynamic_state2,
508 features.extended_dynamic_state2.extendedDynamicState2LogicOp = false; 539 features.extended_dynamic_state2,
509 features.extended_dynamic_state2.extendedDynamicState2PatchControlPoints = false; 540 VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
510 extensions.extended_dynamic_state2 = false;
511 loaded_extensions.erase(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
512 } 541 }
513 } 542 }
514 if (extensions.extended_dynamic_state3 && is_radv) { 543 if (extensions.extended_dynamic_state3 && is_radv) {
@@ -540,9 +569,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
540 if (is_rdna2) { 569 if (is_rdna2) {
541 LOG_WARNING(Render_Vulkan, 570 LOG_WARNING(Render_Vulkan,
542 "RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware"); 571 "RADV has broken VK_EXT_vertex_input_dynamic_state on RDNA2 hardware");
543 features.vertex_input_dynamic_state.vertexInputDynamicState = false; 572 RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
544 extensions.vertex_input_dynamic_state = false; 573 features.vertex_input_dynamic_state,
545 loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); 574 VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
546 } 575 }
547 } 576 }
548 if (extensions.vertex_input_dynamic_state && is_qualcomm) { 577 if (extensions.vertex_input_dynamic_state && is_qualcomm) {
@@ -553,9 +582,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
553 LOG_WARNING( 582 LOG_WARNING(
554 Render_Vulkan, 583 Render_Vulkan,
555 "Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state"); 584 "Qualcomm Adreno 7xx drivers have broken VK_EXT_vertex_input_dynamic_state");
556 features.vertex_input_dynamic_state.vertexInputDynamicState = false; 585 RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
557 extensions.vertex_input_dynamic_state = false; 586 features.vertex_input_dynamic_state,
558 loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); 587 VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
559 } 588 }
560 } 589 }
561 590
@@ -575,8 +604,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
575 if (!features.shader_float16_int8.shaderFloat16) { 604 if (!features.shader_float16_int8.shaderFloat16) {
576 LOG_WARNING(Render_Vulkan, 605 LOG_WARNING(Render_Vulkan,
577 "AMD GCN4 and earlier have broken VK_EXT_sampler_filter_minmax"); 606 "AMD GCN4 and earlier have broken VK_EXT_sampler_filter_minmax");
578 extensions.sampler_filter_minmax = false; 607 RemoveExtension(extensions.sampler_filter_minmax,
579 loaded_extensions.erase(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME); 608 VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME);
580 } 609 }
581 } 610 }
582 611
@@ -584,8 +613,9 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
584 const u32 version = (properties.properties.driverVersion << 3) >> 3; 613 const u32 version = (properties.properties.driverVersion << 3) >> 3;
585 if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) { 614 if (version < VK_MAKE_API_VERSION(27, 20, 100, 0)) {
586 LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state"); 615 LOG_WARNING(Render_Vulkan, "Intel has broken VK_EXT_vertex_input_dynamic_state");
587 extensions.vertex_input_dynamic_state = false; 616 RemoveExtensionFeature(extensions.vertex_input_dynamic_state,
588 loaded_extensions.erase(VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); 617 features.vertex_input_dynamic_state,
618 VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
589 } 619 }
590 } 620 }
591 if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) { 621 if (features.shader_float16_int8.shaderFloat16 && is_intel_windows) {
@@ -612,8 +642,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
612 // mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc 642 // mesa/mesa/-/commit/ff91c5ca42bc80aa411cb3fd8f550aa6fdd16bdc
613 LOG_WARNING(Render_Vulkan, 643 LOG_WARNING(Render_Vulkan,
614 "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor"); 644 "ANV drivers 22.3.0 to 23.1.0 have broken VK_KHR_push_descriptor");
615 extensions.push_descriptor = false; 645 RemoveExtension(extensions.push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
616 loaded_extensions.erase(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME);
617 } 646 }
618 } 647 }
619 if (is_mvk) { 648 if (is_mvk) {
@@ -1007,34 +1036,29 @@ bool Device::GetSuitability(bool requires_swapchain) {
1007 return suitable; 1036 return suitable;
1008} 1037}
1009 1038
1010void Device::RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name) {
1011 if (loaded_extensions.contains(extension_name) && !is_suitable) {
1012 LOG_WARNING(Render_Vulkan, "Removing unsuitable extension {}", extension_name);
1013 loaded_extensions.erase(extension_name);
1014 }
1015}
1016
1017void Device::RemoveUnsuitableExtensions() { 1039void Device::RemoveUnsuitableExtensions() {
1018 // VK_EXT_custom_border_color 1040 // VK_EXT_custom_border_color
1019 extensions.custom_border_color = features.custom_border_color.customBorderColors && 1041 extensions.custom_border_color = features.custom_border_color.customBorderColors &&
1020 features.custom_border_color.customBorderColorWithoutFormat; 1042 features.custom_border_color.customBorderColorWithoutFormat;
1021 RemoveExtensionIfUnsuitable(extensions.custom_border_color, 1043 RemoveExtensionFeatureIfUnsuitable(extensions.custom_border_color, features.custom_border_color,
1022 VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME); 1044 VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME);
1023 1045
1024 // VK_EXT_depth_clip_control 1046 // VK_EXT_depth_clip_control
1025 extensions.depth_clip_control = features.depth_clip_control.depthClipControl; 1047 extensions.depth_clip_control = features.depth_clip_control.depthClipControl;
1026 RemoveExtensionIfUnsuitable(extensions.depth_clip_control, 1048 RemoveExtensionFeatureIfUnsuitable(extensions.depth_clip_control, features.depth_clip_control,
1027 VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME); 1049 VK_EXT_DEPTH_CLIP_CONTROL_EXTENSION_NAME);
1028 1050
1029 // VK_EXT_extended_dynamic_state 1051 // VK_EXT_extended_dynamic_state
1030 extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState; 1052 extensions.extended_dynamic_state = features.extended_dynamic_state.extendedDynamicState;
1031 RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state, 1053 RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state,
1032 VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME); 1054 features.extended_dynamic_state,
1055 VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME);
1033 1056
1034 // VK_EXT_extended_dynamic_state2 1057 // VK_EXT_extended_dynamic_state2
1035 extensions.extended_dynamic_state2 = features.extended_dynamic_state2.extendedDynamicState2; 1058 extensions.extended_dynamic_state2 = features.extended_dynamic_state2.extendedDynamicState2;
1036 RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state2, 1059 RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state2,
1037 VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME); 1060 features.extended_dynamic_state2,
1061 VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME);
1038 1062
1039 // VK_EXT_extended_dynamic_state3 1063 // VK_EXT_extended_dynamic_state3
1040 dynamic_state3_blending = 1064 dynamic_state3_blending =
@@ -1048,35 +1072,38 @@ void Device::RemoveUnsuitableExtensions() {
1048 extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables; 1072 extensions.extended_dynamic_state3 = dynamic_state3_blending || dynamic_state3_enables;
1049 dynamic_state3_blending = dynamic_state3_blending && extensions.extended_dynamic_state3; 1073 dynamic_state3_blending = dynamic_state3_blending && extensions.extended_dynamic_state3;
1050 dynamic_state3_enables = dynamic_state3_enables && extensions.extended_dynamic_state3; 1074 dynamic_state3_enables = dynamic_state3_enables && extensions.extended_dynamic_state3;
1051 RemoveExtensionIfUnsuitable(extensions.extended_dynamic_state3, 1075 RemoveExtensionFeatureIfUnsuitable(extensions.extended_dynamic_state3,
1052 VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME); 1076 features.extended_dynamic_state3,
1077 VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME);
1053 1078
1054 // VK_EXT_provoking_vertex 1079 // VK_EXT_provoking_vertex
1055 extensions.provoking_vertex = 1080 extensions.provoking_vertex =
1056 features.provoking_vertex.provokingVertexLast && 1081 features.provoking_vertex.provokingVertexLast &&
1057 features.provoking_vertex.transformFeedbackPreservesProvokingVertex; 1082 features.provoking_vertex.transformFeedbackPreservesProvokingVertex;
1058 RemoveExtensionIfUnsuitable(extensions.provoking_vertex, 1083 RemoveExtensionFeatureIfUnsuitable(extensions.provoking_vertex, features.provoking_vertex,
1059 VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME); 1084 VK_EXT_PROVOKING_VERTEX_EXTENSION_NAME);
1060 1085
1061 // VK_KHR_shader_atomic_int64 1086 // VK_KHR_shader_atomic_int64
1062 extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics && 1087 extensions.shader_atomic_int64 = features.shader_atomic_int64.shaderBufferInt64Atomics &&
1063 features.shader_atomic_int64.shaderSharedInt64Atomics; 1088 features.shader_atomic_int64.shaderSharedInt64Atomics;
1064 RemoveExtensionIfUnsuitable(extensions.shader_atomic_int64, 1089 RemoveExtensionFeatureIfUnsuitable(extensions.shader_atomic_int64, features.shader_atomic_int64,
1065 VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME); 1090 VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME);
1066 1091
1067 // VK_EXT_shader_demote_to_helper_invocation 1092 // VK_EXT_shader_demote_to_helper_invocation
1068 extensions.shader_demote_to_helper_invocation = 1093 extensions.shader_demote_to_helper_invocation =
1069 features.shader_demote_to_helper_invocation.shaderDemoteToHelperInvocation; 1094 features.shader_demote_to_helper_invocation.shaderDemoteToHelperInvocation;
1070 RemoveExtensionIfUnsuitable(extensions.shader_demote_to_helper_invocation, 1095 RemoveExtensionFeatureIfUnsuitable(extensions.shader_demote_to_helper_invocation,
1071 VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME); 1096 features.shader_demote_to_helper_invocation,
1097 VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
1072 1098
1073 // VK_EXT_subgroup_size_control 1099 // VK_EXT_subgroup_size_control
1074 extensions.subgroup_size_control = 1100 extensions.subgroup_size_control =
1075 features.subgroup_size_control.subgroupSizeControl && 1101 features.subgroup_size_control.subgroupSizeControl &&
1076 properties.subgroup_size_control.minSubgroupSize <= GuestWarpSize && 1102 properties.subgroup_size_control.minSubgroupSize <= GuestWarpSize &&
1077 properties.subgroup_size_control.maxSubgroupSize >= GuestWarpSize; 1103 properties.subgroup_size_control.maxSubgroupSize >= GuestWarpSize;
1078 RemoveExtensionIfUnsuitable(extensions.subgroup_size_control, 1104 RemoveExtensionFeatureIfUnsuitable(extensions.subgroup_size_control,
1079 VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME); 1105 features.subgroup_size_control,
1106 VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME);
1080 1107
1081 // VK_EXT_transform_feedback 1108 // VK_EXT_transform_feedback
1082 extensions.transform_feedback = 1109 extensions.transform_feedback =
@@ -1086,24 +1113,27 @@ void Device::RemoveUnsuitableExtensions() {
1086 properties.transform_feedback.maxTransformFeedbackBuffers > 0 && 1113 properties.transform_feedback.maxTransformFeedbackBuffers > 0 &&
1087 properties.transform_feedback.transformFeedbackQueries && 1114 properties.transform_feedback.transformFeedbackQueries &&
1088 properties.transform_feedback.transformFeedbackDraw; 1115 properties.transform_feedback.transformFeedbackDraw;
1089 RemoveExtensionIfUnsuitable(extensions.transform_feedback, 1116 RemoveExtensionFeatureIfUnsuitable(extensions.transform_feedback, features.transform_feedback,
1090 VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME); 1117 VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME);
1091 1118
1092 // VK_EXT_vertex_input_dynamic_state 1119 // VK_EXT_vertex_input_dynamic_state
1093 extensions.vertex_input_dynamic_state = 1120 extensions.vertex_input_dynamic_state =
1094 features.vertex_input_dynamic_state.vertexInputDynamicState; 1121 features.vertex_input_dynamic_state.vertexInputDynamicState;
1095 RemoveExtensionIfUnsuitable(extensions.vertex_input_dynamic_state, 1122 RemoveExtensionFeatureIfUnsuitable(extensions.vertex_input_dynamic_state,
1096 VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME); 1123 features.vertex_input_dynamic_state,
1124 VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
1097 1125
1098 // VK_KHR_pipeline_executable_properties 1126 // VK_KHR_pipeline_executable_properties
1099 if (Settings::values.renderer_shader_feedback.GetValue()) { 1127 if (Settings::values.renderer_shader_feedback.GetValue()) {
1100 extensions.pipeline_executable_properties = 1128 extensions.pipeline_executable_properties =
1101 features.pipeline_executable_properties.pipelineExecutableInfo; 1129 features.pipeline_executable_properties.pipelineExecutableInfo;
1102 RemoveExtensionIfUnsuitable(extensions.pipeline_executable_properties, 1130 RemoveExtensionFeatureIfUnsuitable(extensions.pipeline_executable_properties,
1103 VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); 1131 features.pipeline_executable_properties,
1132 VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
1104 } else { 1133 } else {
1105 extensions.pipeline_executable_properties = false; 1134 RemoveExtensionFeature(extensions.pipeline_executable_properties,
1106 loaded_extensions.erase(VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME); 1135 features.pipeline_executable_properties,
1136 VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME);
1107 } 1137 }
1108 1138
1109 // VK_KHR_workgroup_memory_explicit_layout 1139 // VK_KHR_workgroup_memory_explicit_layout
@@ -1113,8 +1143,9 @@ void Device::RemoveUnsuitableExtensions() {
1113 features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess && 1143 features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout8BitAccess &&
1114 features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess && 1144 features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayout16BitAccess &&
1115 features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout; 1145 features.workgroup_memory_explicit_layout.workgroupMemoryExplicitLayoutScalarBlockLayout;
1116 RemoveExtensionIfUnsuitable(extensions.workgroup_memory_explicit_layout, 1146 RemoveExtensionFeatureIfUnsuitable(extensions.workgroup_memory_explicit_layout,
1117 VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME); 1147 features.workgroup_memory_explicit_layout,
1148 VK_KHR_WORKGROUP_MEMORY_EXPLICIT_LAYOUT_EXTENSION_NAME);
1118} 1149}
1119 1150
1120void Device::SetupFamilies(VkSurfaceKHR surface) { 1151void Device::SetupFamilies(VkSurfaceKHR surface) {
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index d8dd41e51..488fdd313 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -639,8 +639,17 @@ private:
639 639
640 // Remove extensions which have incomplete feature support. 640 // Remove extensions which have incomplete feature support.
641 void RemoveUnsuitableExtensions(); 641 void RemoveUnsuitableExtensions();
642
643 void RemoveExtension(bool& extension, const std::string& extension_name);
642 void RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name); 644 void RemoveExtensionIfUnsuitable(bool is_suitable, const std::string& extension_name);
643 645
646 template <typename Feature>
647 void RemoveExtensionFeature(bool& extension, Feature& feature,
648 const std::string& extension_name);
649 template <typename Feature>
650 void RemoveExtensionFeatureIfUnsuitable(bool is_suitable, Feature& feature,
651 const std::string& extension_name);
652
644 /// Sets up queue families. 653 /// Sets up queue families.
645 void SetupFamilies(VkSurfaceKHR surface); 654 void SetupFamilies(VkSurfaceKHR surface);
646 655