Halide 22.0.0 Halide compiler and libraries

vulkan_extensions.h
Go to the documentation of this file.
1#ifndef HALIDE_RUNTIME_VULKAN_EXTENSIONS_H
2#define HALIDE_RUNTIME_VULKAN_EXTENSIONS_H
3
4#include "vulkan_internal.h"
5
6// --------------------------------------------------------------------------
7
8namespace Halide {
9namespace Runtime {
10namespace Internal {
11namespace Vulkan {
12
13// --------------------------------------------------------------------------
14
15 WEAK char layer_names[1024];
16 WEAK ScopedSpinLock::AtomicFlag layer_names_lock = 0;
17 WEAK bool layer_names_initialized = false;
18
19 WEAK char extension_names[1024];
20 WEAK ScopedSpinLock::AtomicFlag extension_names_lock = 0;
21 WEAK bool extension_names_initialized = false;
22
23 WEAK char device_type[256];
24 WEAK ScopedSpinLock::AtomicFlag device_type_lock = 0;
25 WEAK bool device_type_initialized = false;
26
27 WEAK char build_options[1024];
28 WEAK ScopedSpinLock::AtomicFlag build_options_lock = 0;
29 WEAK bool build_options_initialized = false;
30
31 WEAK char alloc_config[1024];
32 WEAK ScopedSpinLock::AtomicFlag alloc_config_lock = 0;
33 WEAK bool alloc_config_initialized = false;
34
35// --------------------------------------------------------------------------
36namespace {
37
38void vk_set_layer_names_internal(const char *n) {
39 if (n) {
40 size_t buffer_size = sizeof(layer_names) / sizeof(layer_names[0]);
41 StringUtils::copy_up_to(layer_names, n, buffer_size);
42 } else {
43 layer_names[0] = 0;
44 }
45 layer_names_initialized = true;
46}
47
48const char *vk_get_layer_names_internal(void *user_context) {
49 if (!layer_names_initialized) {
50 const char *value = getenv("HL_VK_LAYERS");
51 if (value == nullptr) {
52 value = getenv("VK_INSTANCE_LAYERS");
53 }
54 vk_set_layer_names_internal(value);
55 }
56 return layer_names;
57}
58
59void vk_set_extension_names_internal(const char *n) {
60 if (n) {
61 size_t buffer_size = sizeof(extension_names) / sizeof(extension_names[0]);
62 StringUtils::copy_up_to(extension_names, n, buffer_size);
63 } else {
64 extension_names[0] = 0;
65 }
66 extension_names_initialized = true;
67}
68
69const char *vk_get_extension_names_internal(void *user_context) {
70 if (!extension_names_initialized) {
71 const char *name = getenv("HL_VK_EXTENSIONS");
72 vk_set_extension_names_internal(name);
73 }
74 return extension_names;
75}
76
77void vk_set_device_type_internal(const char *n) {
78 if (n) {
79 size_t buffer_size = sizeof(device_type) / sizeof(device_type[0]);
80 StringUtils::copy_up_to(device_type, n, buffer_size);
81 } else {
82 device_type[0] = 0;
83 }
84 device_type_initialized = true;
85}
86
87const char *vk_get_device_type_internal(void *user_context) {
88 if (!device_type_initialized) {
89 const char *name = getenv("HL_VK_DEVICE_TYPE");
90 vk_set_device_type_internal(name);
91 }
92 return device_type;
93}
94
95void vk_set_build_options_internal(const char *n) {
96 if (n) {
97 size_t buffer_size = sizeof(build_options) / sizeof(build_options[0]);
98 StringUtils::copy_up_to(build_options, n, buffer_size);
99 } else {
100 build_options[0] = 0;
101 }
102 build_options_initialized = true;
103}
104
105const char *vk_get_build_options_internal(void *user_context) {
106 if (!build_options_initialized) {
107 const char *name = getenv("HL_VK_BUILD_OPTIONS");
108 vk_set_build_options_internal(name);
109 }
110 return build_options;
111}
112
113void vk_set_alloc_config_internal(const char *n) {
114 if (n) {
115 size_t buffer_size = sizeof(alloc_config) / sizeof(alloc_config[0]);
116 StringUtils::copy_up_to(alloc_config, n, buffer_size);
117 } else {
118 alloc_config[0] = 0;
119 }
120 alloc_config_initialized = true;
121}
122
123const char *vk_get_alloc_config_internal(void *user_context) {
124 if (!alloc_config_initialized) {
125 const char *name = getenv("HL_VK_ALLOC_CONFIG");
126 vk_set_alloc_config_internal(name);
127 }
128 return alloc_config;
129}
130
131// --------------------------------------------------------------------------
132
133 uint32_t vk_get_requested_layers(void *user_context, StringTable &layer_table) {
134 ScopedSpinLock lock(&layer_names_lock);
135 const char *layer_names = vk_get_layer_names_internal(user_context);
136 return layer_table.parse(user_context, layer_names, HL_VK_ENV_DELIM);
137}
138
139 uint32_t vk_get_required_instance_extensions(void *user_context, StringTable &ext_table) {
140 // Don't require any instance extensions (unless there are features we can't query for later ...)
141 return 0;
142}
143
144 uint32_t vk_get_optional_instance_extensions(void *user_context, StringTable &ext_table) {
145 const char *optional_ext_table[] = {
146 VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, //< promoted to core in v1.1
147 VK_EXT_DEBUG_UTILS_EXTENSION_NAME}; //< optional on all versions
148 const uint32_t optional_ext_count = sizeof(optional_ext_table) / sizeof(optional_ext_table[0]);
149 ext_table.fill(user_context, (const char **)optional_ext_table, optional_ext_count);
150 return optional_ext_count;
151}
152
153 uint32_t vk_get_supported_instance_extensions(void *user_context, StringTable &ext_table) {
154
155 PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
156 vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceExtensionProperties");
157
158 if (vkEnumerateInstanceExtensionProperties == nullptr) {
159 debug(user_context) << "Vulkan: Missing vkEnumerateInstanceExtensionProperties proc address! Invalid loader?!\n";
160 return 0;
161 }
162
163 debug(user_context) << "Vulkan: Checking vkEnumerateInstanceExtensionProperties for extensions ...\n";
164
165 uint32_t avail_ext_count = 0;
166 vkEnumerateInstanceExtensionProperties(nullptr, &avail_ext_count, nullptr);
167
168 if (avail_ext_count) {
169 BlockStorage::Config config;
170 config.entry_size = sizeof(VkExtensionProperties);
171 config.minimum_capacity = avail_ext_count;
172
173 BlockStorage extension_properties(user_context, config);
174 extension_properties.resize(user_context, avail_ext_count);
175
176 vkEnumerateInstanceExtensionProperties(nullptr,
177 &avail_ext_count, static_cast<VkExtensionProperties *>(extension_properties.data()));
178
179 for (uint32_t n = 0; n < avail_ext_count; ++n) {
180 const VkExtensionProperties *properties = static_cast<const VkExtensionProperties *>(extension_properties[n]);
181 debug(user_context) << " [" << n << "]: " << properties->extensionName << "\n";
182 }
183
184 ext_table.resize(user_context, avail_ext_count);
185 for (uint32_t n = 0; n < avail_ext_count; ++n) {
186 const VkExtensionProperties *properties = static_cast<const VkExtensionProperties *>(extension_properties[n]);
187 ext_table.assign(user_context, n, properties->extensionName);
188 }
189 }
190 debug(user_context) << "Vulkan: vkEnumerateInstanceExtensionProperties found " << avail_ext_count << " extensions ...\n";
191 return avail_ext_count;
192}
193
194 uint32_t vk_get_required_device_extensions(void *user_context, uint32_t major_version, uint32_t minor_version, StringTable &ext_table) {
195 // Only require device extensions that have *not* been promoted to the current major, minor version
196 // supported by the Vulkan device (since the extension string may be missing once it has been promoted)
197 const char *before_v1p1_ext_table[] = {
198 VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME}; // promoted to core in v1.1
199 const uint32_t before_v1p1_ext_count = sizeof(before_v1p1_ext_table) / sizeof(before_v1p1_ext_table[0]);
200
201 const char *before_v1p2_ext_table[] = {
202 before_v1p1_ext_table[0],
203 VK_KHR_8BIT_STORAGE_EXTENSION_NAME}; // promoted to core in v1.2
204 const uint32_t before_v1p2_ext_count = sizeof(before_v1p2_ext_table) / sizeof(before_v1p2_ext_table[0]);
205
206 uint32_t required_ext_count = 0;
207 if (major_version >= 1) {
208 if (minor_version < 1) {
209 ext_table.fill(user_context, (const char **)before_v1p1_ext_table, before_v1p1_ext_count);
210 required_ext_count = before_v1p1_ext_count;
211 } else if (minor_version < 2) {
212 ext_table.fill(user_context, (const char **)before_v1p2_ext_table, before_v1p2_ext_count);
213 required_ext_count = before_v1p2_ext_count;
214 }
215 }
216 return required_ext_count;
217}
218
219 uint32_t vk_get_optional_device_extensions(void *user_context, uint32_t major_version, uint32_t minor_version, StringTable &ext_table) {
220 // Only add optional device extensions that have *not* been promoted to the current major, minor version
221 // supported by the Vulkan device (since the extension string may be missing once it has been promoted)
222 const char *before_v1p1_ext_table[] = {
223 VK_KHR_16BIT_STORAGE_EXTENSION_NAME}; //< promoted to core in v1.1
224 const uint32_t before_v1p1_ext_count = sizeof(before_v1p1_ext_table) / sizeof(before_v1p1_ext_table[0]);
225
226 const char *before_v1p2_ext_table[] = {
227 before_v1p1_ext_table[0],
228 "VK_KHR_portability_subset", //< requires v1.1, always optional, necessary for running under Molten (aka Vulkan on Mac)
229 VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, //< promoted to core in v1.2
230 VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME}; //< promoted to core in v1.2
231 const uint32_t before_v1p2_ext_count = sizeof(before_v1p2_ext_table) / sizeof(before_v1p2_ext_table[0]);
232
233 const char *v1p3_ext_table[] = {
234 "VK_KHR_portability_subset", //< requires v1.1, always optional, necessary for running under Molten (aka Vulkan on Mac)
235 VK_KHR_MAINTENANCE_5_EXTENSION_NAME}; //< requires v1.3
236 const uint32_t v1p3_ext_count = sizeof(v1p3_ext_table) / sizeof(v1p3_ext_table[0]);
237
238 uint32_t optional_ext_count = 0;
239 if (major_version >= 1) {
240 if (minor_version < 1) {
241 ext_table.fill(user_context, (const char **)before_v1p1_ext_table, before_v1p1_ext_count);
242 optional_ext_count = before_v1p1_ext_count;
243 } else if (minor_version < 2) {
244 ext_table.fill(user_context, (const char **)before_v1p2_ext_table, before_v1p2_ext_count);
245 optional_ext_count = before_v1p2_ext_count;
246 } else if (minor_version >= 3) {
247 ext_table.fill(user_context, (const char **)v1p3_ext_table, v1p3_ext_count);
248 optional_ext_count = v1p3_ext_count;
249 }
250 }
251 return optional_ext_count;
252}
253
254 uint32_t vk_get_supported_device_extensions(void *user_context, VkPhysicalDevice physical_device, StringTable &ext_table) {
255 debug(user_context) << "vk_get_supported_device_extensions\n";
256 if (vkEnumerateDeviceExtensionProperties == nullptr) {
257 debug(user_context) << "Vulkan: Missing vkEnumerateDeviceExtensionProperties proc address! Invalid loader?!\n";
258 return 0;
259 }
260
261 debug(user_context) << "Vulkan: Checking vkEnumerateDeviceExtensionProperties for extensions ...\n";
262
263 uint32_t avail_ext_count = 0;
264 vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &avail_ext_count, nullptr);
265 if (avail_ext_count > 0) {
266 BlockStorage::Config config;
267 config.entry_size = sizeof(VkExtensionProperties);
268 config.minimum_capacity = avail_ext_count;
269
270 BlockStorage extension_properties(user_context, config);
271 extension_properties.resize(user_context, avail_ext_count);
272
273 vkEnumerateDeviceExtensionProperties(physical_device, nullptr,
274 &avail_ext_count, static_cast<VkExtensionProperties *>(extension_properties.data()));
275
276 for (uint32_t n = 0; n < avail_ext_count; ++n) {
277 const VkExtensionProperties *properties = static_cast<const VkExtensionProperties *>(extension_properties[n]);
278 debug(user_context) << " [" << n << "]: " << properties->extensionName << "\n";
279 }
280
281 ext_table.resize(user_context, avail_ext_count);
282 for (uint32_t n = 0; n < avail_ext_count; ++n) {
283 const VkExtensionProperties *properties = static_cast<const VkExtensionProperties *>(extension_properties[n]);
284 ext_table.assign(user_context, n, properties->extensionName);
285 }
286 }
287
288 debug(user_context) << "Vulkan: vkEnumerateDeviceExtensionProperties found " << avail_ext_count << " extensions ...\n";
289 return avail_ext_count;
290}
291
292bool vk_validate_required_extension_support(void *user_context,
293 const StringTable &required_extensions,
294 const StringTable &supported_extensions) {
295 debug(user_context) << "Vulkan: Validating " << uint32_t(required_extensions.size()) << " extensions ...\n";
296 bool validated = true;
297 for (uint32_t n = 0; n < required_extensions.size(); ++n) {
298 const char *extension = required_extensions[n];
299 if (!supported_extensions.contains(extension)) {
300 debug(user_context) << "Vulkan: Missing required extension: '" << extension << "'!\n";
301 validated = false;
302 }
303 }
304 return validated;
305}
306
307// --------------------------------------------------------------------------
308
309} // namespace
310} // namespace Vulkan
311} // namespace Internal
312} // namespace Runtime
313} // namespace Halide
314
315// --------------------------------------------------------------------------
316
317using namespace Halide::Runtime::Internal::Vulkan;
318
319// --------------------------------------------------------------------------
320
321extern "C" {
322
323// --------------------------------------------------------------------------
324
325 WEAK void halide_vulkan_set_layer_names(const char *n) {
326 ScopedSpinLock lock(&layer_names_lock);
327 vk_set_layer_names_internal(n);
328}
329
330 WEAK const char *halide_vulkan_get_layer_names(void *user_context) {
331 ScopedSpinLock lock(&layer_names_lock);
332 return vk_get_layer_names_internal(user_context);
333}
334
335 WEAK void halide_vulkan_set_extension_names(const char *n) {
336 ScopedSpinLock lock(&extension_names_lock);
337 vk_set_extension_names_internal(n);
338}
339
340 WEAK const char *halide_vulkan_get_extension_names(void *user_context) {
341 ScopedSpinLock lock(&extension_names_lock);
342 return vk_get_extension_names_internal(user_context);
343}
344
345 WEAK void halide_vulkan_set_device_type(const char *n) {
346 ScopedSpinLock lock(&device_type_lock);
347 vk_set_device_type_internal(n);
348}
349
350 WEAK const char *halide_vulkan_get_device_type(void *user_context) {
351 ScopedSpinLock lock(&device_type_lock);
352 return vk_get_device_type_internal(user_context);
353}
354
355 WEAK void halide_vulkan_set_build_options(const char *n) {
356 ScopedSpinLock lock(&build_options_lock);
357 vk_set_build_options_internal(n);
358}
359
360 WEAK const char *halide_vulkan_get_build_options(void *user_context) {
361 ScopedSpinLock lock(&build_options_lock);
362 return vk_get_build_options_internal(user_context);
363}
364
365 WEAK void halide_vulkan_set_alloc_config(const char *n) {
366 ScopedSpinLock lock(&alloc_config_lock);
367 vk_set_alloc_config_internal(n);
368}
369
370 WEAK const char *halide_vulkan_get_alloc_config(void *user_context) {
371 ScopedSpinLock lock(&alloc_config_lock);
372 return vk_get_alloc_config_internal(user_context);
373}
374
375// --------------------------------------------------------------------------
376
377} // extern "C"
378
379#endif // HALIDE_RUNTIME_VULKAN_EXTENSIONS_H
debug
#define debug(n)
For optional debugging during codegen, use the debug macro as follows:
Definition: Debug.h:52
Halide::Runtime::Internal::BlockStorage
Definition: block_storage.h:18
Halide::Runtime::Internal::BlockStorage::resize
void resize(void *user_context, size_t entry_count, bool realloc=true)
Definition: block_storage.h:204
Halide::Runtime::Internal::BlockStorage::data
void * data()
Definition: block_storage.h:354
Halide::Runtime::Internal::StringTable
Definition: string_table.h:15
Halide::Runtime::Internal::StringTable::parse
size_t parse(void *user_context, const char *str, const char *delim)
Definition: string_table.h:159
Halide::Runtime::Internal::StringTable::assign
void assign(void *user_context, size_t index, const char *str, size_t length=0)
Definition: string_table.h:134
Halide::Runtime::Internal::StringTable::size
size_t size() const
Definition: string_table.h:54
Halide::Runtime::Internal::StringTable::resize
void resize(void *user_context, size_t capacity)
Definition: string_table.h:89
Halide::Runtime::Internal::StringTable::fill
void fill(void *user_context, const char **array, size_t count)
Definition: string_table.h:125
Halide::Runtime::Internal::StringTable::contains
bool contains(const char *str) const
Definition: string_table.h:191
Halide::Runtime::Internal::Vulkan
Definition: vulkan_context.h:17
Halide::Runtime::Internal::Vulkan::layer_names_initialized
WEAK bool layer_names_initialized
Definition: vulkan_extensions.h:17
Halide::Runtime::Internal::Vulkan::alloc_config_lock
WEAK ScopedSpinLock::AtomicFlag alloc_config_lock
Definition: vulkan_extensions.h:32
Halide::Runtime::Internal::Vulkan::build_options
WEAK char build_options[1024]
Definition: vulkan_extensions.h:27
Halide::Runtime::Internal::Vulkan::layer_names
WEAK char layer_names[1024]
Definition: vulkan_extensions.h:15
Halide::Runtime::Internal::Vulkan::build_options_initialized
WEAK bool build_options_initialized
Definition: vulkan_extensions.h:29
Halide::Runtime::Internal::Vulkan::extension_names_lock
WEAK ScopedSpinLock::AtomicFlag extension_names_lock
Definition: vulkan_extensions.h:20
Halide::Runtime::Internal::Vulkan::device_type_initialized
WEAK bool device_type_initialized
Definition: vulkan_extensions.h:25
Halide::Runtime::Internal::Vulkan::alloc_config_initialized
WEAK bool alloc_config_initialized
Definition: vulkan_extensions.h:33
Halide::Runtime::Internal::Vulkan::layer_names_lock
WEAK ScopedSpinLock::AtomicFlag layer_names_lock
Definition: vulkan_extensions.h:16
Halide::Runtime::Internal::Vulkan::build_options_lock
WEAK ScopedSpinLock::AtomicFlag build_options_lock
Definition: vulkan_extensions.h:28
Halide::Runtime::Internal::Vulkan::alloc_config
WEAK char alloc_config[1024]
Definition: vulkan_extensions.h:31
Halide::Runtime::Internal::Vulkan::device_type
WEAK char device_type[256]
Definition: vulkan_extensions.h:23
Halide::Runtime::Internal::Vulkan::extension_names_initialized
WEAK bool extension_names_initialized
Definition: vulkan_extensions.h:21
Halide::Runtime::Internal::Vulkan::device_type_lock
WEAK ScopedSpinLock::AtomicFlag device_type_lock
Definition: vulkan_extensions.h:24
Halide::Runtime::Internal::Vulkan::extension_names
WEAK char extension_names[1024]
Definition: vulkan_extensions.h:19
Halide
This file defines the class FunctionDAG, which is our representation of a Halide pipeline,...
Definition: AbstractGenerator.h:19
Halide::LinkageType::Internal
@ Internal
Not visible externally, similar to 'static' linkage in C.
Halide::DeviceAPI::Vulkan
@ Vulkan
uint32_t
unsigned __INT32_TYPE__ uint32_t
Definition: runtime_internal.h:25
WEAK
#define WEAK
Definition: runtime_internal.h:52
getenv
char * getenv(const char *)
Halide::Runtime::Internal::BlockStorage::Config
Definition: block_storage.h:23
Halide::Runtime::Internal::BlockStorage::Config::minimum_capacity
uint32_t minimum_capacity
Definition: block_storage.h:26
Halide::Runtime::Internal::BlockStorage::Config::entry_size
uint32_t entry_size
Definition: block_storage.h:24
Halide::Runtime::Internal::ScopedSpinLock
Definition: scoped_spin_lock.h:9
Halide::Runtime::Internal::ScopedSpinLock::AtomicFlag
char AtomicFlag
Definition: scoped_spin_lock.h:11
Halide::Runtime::Internal::StringUtils::copy_up_to
static size_t copy_up_to(char *dst, const char *src, size_t max_chars)
Definition: string_storage.h:72
halide_vulkan_set_layer_names
WEAK void halide_vulkan_set_layer_names(const char *n)
Definition: vulkan_extensions.h:325
halide_vulkan_set_build_options
WEAK void halide_vulkan_set_build_options(const char *n)
Definition: vulkan_extensions.h:355
halide_vulkan_set_extension_names
WEAK void halide_vulkan_set_extension_names(const char *n)
Definition: vulkan_extensions.h:335
halide_vulkan_set_device_type
WEAK void halide_vulkan_set_device_type(const char *n)
Definition: vulkan_extensions.h:345
halide_vulkan_get_alloc_config
WEAK const char * halide_vulkan_get_alloc_config(void *user_context)
Definition: vulkan_extensions.h:370
halide_vulkan_get_layer_names
WEAK const char * halide_vulkan_get_layer_names(void *user_context)
Definition: vulkan_extensions.h:330
halide_vulkan_set_alloc_config
WEAK void halide_vulkan_set_alloc_config(const char *n)
Definition: vulkan_extensions.h:365
halide_vulkan_get_build_options
WEAK const char * halide_vulkan_get_build_options(void *user_context)
Definition: vulkan_extensions.h:360
halide_vulkan_get_extension_names
WEAK const char * halide_vulkan_get_extension_names(void *user_context)
Definition: vulkan_extensions.h:340
halide_vulkan_get_device_type
WEAK const char * halide_vulkan_get_device_type(void *user_context)
Definition: vulkan_extensions.h:350
HL_VK_ENV_DELIM
#define HL_VK_ENV_DELIM
Definition: vulkan_interface.h:14
vulkan_internal.h
user_context
void * user_context
Definition: vulkan_resources.h:178