|
10 | 10 |
|
11 | 11 | #include <executorch/backends/vulkan/runtime/vk_api/Adapter.h> |
12 | 12 |
|
| 13 | +#include <cstring> |
13 | 14 | #include <iomanip> |
14 | 15 | #include <sstream> |
15 | 16 |
|
@@ -83,7 +84,7 @@ void populate_queue_info( |
83 | 84 | } |
84 | 85 |
|
85 | 86 | VkDevice create_logical_device( |
86 | | - const PhysicalDevice& physical_device, |
| 87 | + PhysicalDevice& physical_device, |
87 | 88 | const uint32_t num_queues_to_create, |
88 | 89 | std::vector<Adapter::Queue>& queues, |
89 | 90 | std::vector<uint32_t>& queue_usage) { |
@@ -217,15 +218,46 @@ VkDevice create_logical_device( |
217 | 218 | #endif /* VK_NV_cooperative_matrix2 */ |
218 | 219 |
|
219 | 220 | #ifdef VK_EXT_subgroup_size_control |
220 | | - // Only enable the feature struct if the extension was actually requested |
221 | | - // and the feature flag is set on the physical device. The extension itself |
222 | | - // is filtered into enabled_device_extensions by |
223 | | - // find_requested_device_extensions. |
| 221 | + // The subgroup size control feature struct may only be chained into |
| 222 | + // VkDeviceCreateInfo.pNext if the feature is actually going to be enabled on |
| 223 | + // the logical device. It can be enabled via two routes: |
| 224 | + // 1. The VK_EXT_subgroup_size_control extension is enabled, or |
| 225 | + // 2. It is available as core (promoted to core in Vulkan 1.3), which |
| 226 | + // requires both the instance and the physical device to be at 1.3+. |
| 227 | + // On Vulkan 1.3-core drivers the extension is frequently not advertised as a |
| 228 | + // separate string, so checking enabled_device_extensions alone is not |
| 229 | + // sufficient. Chaining the struct without either route being available is |
| 230 | + // invalid usage and crashes device/pipeline creation with |
| 231 | + // VK_ERROR_INITIALIZATION_FAILED. |
| 232 | + bool subgroup_size_control_extension_enabled = false; |
| 233 | + for (const auto& ext : enabled_device_extensions) { |
| 234 | + if (strcmp(ext, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME) == 0) { |
| 235 | + subgroup_size_control_extension_enabled = true; |
| 236 | + break; |
| 237 | + } |
| 238 | + } |
| 239 | + |
| 240 | + bool subgroup_size_control_core_available = false; |
| 241 | +#if defined(VK_VERSION_1_3) |
| 242 | + const bool device_supports_1_3 = physical_device.api_version_major > 1 || |
| 243 | + (physical_device.api_version_major == 1 && |
| 244 | + physical_device.api_version_minor >= 3); |
| 245 | + const bool instance_supports_1_3 = |
| 246 | + select_instance_api_version() >= VK_API_VERSION_1_3; |
| 247 | + subgroup_size_control_core_available = |
| 248 | + device_supports_1_3 && instance_supports_1_3; |
| 249 | +#endif /* VK_VERSION_1_3 */ |
| 250 | + |
224 | 251 | VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroup_size_control_features{ |
225 | 252 | physical_device.subgroup_size_control_features}; |
226 | | - if (physical_device.supports_subgroup_size_control) { |
| 253 | + if (physical_device.supports_subgroup_size_control && |
| 254 | + (subgroup_size_control_extension_enabled || |
| 255 | + subgroup_size_control_core_available)) { |
227 | 256 | subgroup_size_control_features.pNext = extension_list_top; |
228 | 257 | extension_list_top = &subgroup_size_control_features; |
| 258 | + } else { |
| 259 | + physical_device.supports_subgroup_size_control = false; |
| 260 | + physical_device.supports_compute_full_subgroups = false; |
229 | 261 | } |
230 | 262 | #endif /* VK_EXT_subgroup_size_control */ |
231 | 263 |
|
|
0 commit comments