Coverage Report

Created: 2026-10-19 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vulkan-loader/loader/loader_common.h
Line
Count
Source
1
/*
2
 *
3
 * Copyright (c) 2014-2022 The Khronos Group Inc.
4
 * Copyright (c) 2014-2022 Valve Corporation
5
 * Copyright (c) 2014-2022 LunarG, Inc.
6
 * Copyright (C) 2015 Google Inc.
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 *
20
 * Author: Jon Ashburn <jon@lunarg.com>
21
 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
22
 * Author: Chia-I Wu <olvaffe@gmail.com>
23
 * Author: Chia-I Wu <olv@lunarg.com>
24
 * Author: Mark Lobodzinski <mark@LunarG.com>
25
 * Author: Lenny Komow <lenny@lunarg.com>
26
 * Author: Charles Giessen <charles@lunarg.com>
27
 *
28
 */
29
30
#pragma once
31
32
#include "vulkan/vk_platform.h"
33
#include <vulkan/vulkan.h>
34
#include <vulkan/vk_layer.h>
35
#include <vulkan/vk_icd.h>
36
37
#include "vk_loader_platform.h"
38
#include "vk_loader_layer.h"
39
#include "vk_layer_dispatch_table.h"
40
#include "vk_loader_extensions.h"
41
42
#include "settings.h"
43
44
typedef enum VkStringErrorFlagBits {
45
    VK_STRING_ERROR_NONE = 0x00000000,
46
    VK_STRING_ERROR_LENGTH = 0x00000001,
47
    VK_STRING_ERROR_BAD_DATA = 0x00000002,
48
    VK_STRING_ERROR_NULL_PTR = 0x00000004,
49
} VkStringErrorFlagBits;
50
typedef VkFlags VkStringErrorFlags;
51
52
static const int MaxLoaderStringLength = 256;           // 0xFF;
53
static const unsigned char UTF8_ONE_BYTE_CODE = 192;    // 0xC0;
54
static const unsigned char UTF8_ONE_BYTE_MASK = 224;    // 0xE0;
55
static const unsigned char UTF8_TWO_BYTE_CODE = 224;    // 0xE0;
56
static const unsigned char UTF8_TWO_BYTE_MASK = 240;    // 0xF0;
57
static const unsigned char UTF8_THREE_BYTE_CODE = 240;  // 0xF0;
58
static const unsigned char UTF8_THREE_BYTE_MASK = 248;  // 0xF8;
59
static const unsigned char UTF8_DATA_BYTE_CODE = 128;   // 0x80;
60
static const unsigned char UTF8_DATA_BYTE_MASK = 192;   // 0xC0;
61
62
// 32-bit FNV-1a (https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function). Mirrored
63
// byte-for-byte in Python as loader_hash_string() in scripts/generators/loader_extension_generator.py,
64
// which precomputes the hash constants embedded in loader/generated/vk_loader_extensions.c - keep both in
65
// sync or those constants stop matching this function (see HashString.MatchesGeneratorEmbeddedConstants in
66
// tests/loader_hash_string_tests.cpp).
67
//
68
// Used as a cheap pre-filter before the strcmp confirmation when resolving entry point names
69
// (vkGet{Instance,Device}ProcAddr): a hash match still falls through to a switch/case-guarded strcmp before
70
// anything is returned, so a collision can never produce a wrong lookup - at worst it costs one extra
71
// strcmp. Bounded by MaxLoaderStringLength so a non-NUL-terminated or adversarially long input can't make
72
// this scan past a bounded byte count the way an unbounded `while (*str)` would. MaxLoaderStringLength is
73
// an unrelated pre-existing constant reused here for convenience, not a bound derived from entry point
74
// name lengths; every real entry point name is far shorter than the cap, so this never changes the hash
75
// of a valid name.
76
0
static inline uint32_t loader_hash_string(const char *str) {
77
0
    uint32_t hash = 2166136261u;
78
0
    for (uint32_t i = 0; i < (uint32_t)MaxLoaderStringLength && str[i]; ++i) {
79
0
        hash ^= (uint8_t)str[i];
80
0
        hash *= 16777619u;
81
0
    }
82
0
    return hash;
83
0
}
Unexecuted instantiation: json_load_fuzzer.c:loader_hash_string
Unexecuted instantiation: cJSON.c:loader_hash_string
Unexecuted instantiation: loader_json.c:loader_hash_string
Unexecuted instantiation: log.c:loader_hash_string
Unexecuted instantiation: allocation.c:loader_hash_string
Unexecuted instantiation: debug_utils.c:loader_hash_string
Unexecuted instantiation: loader.c:loader_hash_string
Unexecuted instantiation: loader_environment.c:loader_hash_string
Unexecuted instantiation: loader_linux.c:loader_hash_string
Unexecuted instantiation: settings.c:loader_hash_string
Unexecuted instantiation: terminator.c:loader_hash_string
Unexecuted instantiation: trampoline.c:loader_hash_string
Unexecuted instantiation: unknown_function_handling.c:loader_hash_string
Unexecuted instantiation: wsi.c:loader_hash_string
Unexecuted instantiation: extension_manual.c:loader_hash_string
Unexecuted instantiation: gpa_helper.c:loader_hash_string
84
85
// form of all dynamic lists/arrays
86
// only the list element should be changed
87
struct loader_generic_list {
88
    size_t capacity;
89
    uint32_t count;
90
    void *list;
91
};
92
93
struct loader_string_list {
94
    uint32_t allocated_count;
95
    uint32_t count;
96
    char **list;
97
};
98
99
struct loader_extension_list {
100
    size_t capacity;
101
    uint32_t count;
102
    VkExtensionProperties *list;
103
};
104
105
struct loader_dev_ext_props {
106
    VkExtensionProperties props;
107
    struct loader_string_list entrypoints;
108
};
109
110
struct loader_device_extension_list {
111
    size_t capacity;
112
    uint32_t count;
113
    struct loader_dev_ext_props *list;
114
};
115
116
struct loader_used_object_status {
117
    VkBool32 status;
118
    VkAllocationCallbacks allocation_callbacks;
119
};
120
121
struct loader_used_object_list {
122
    size_t capacity;
123
    uint32_t padding;  // count variable isn't used
124
    struct loader_used_object_status *list;
125
};
126
127
struct loader_surface_allocation {
128
    VkSurfaceKHR surface;
129
    VkAllocationCallbacks allocation_callbacks;
130
};
131
132
struct loader_surface_list {
133
    size_t capacity;
134
    uint32_t padding;  // count variable isn't used
135
    VkSurfaceKHR *list;
136
};
137
138
struct loader_debug_utils_messenger_list {
139
    size_t capacity;
140
    uint32_t padding;  // count variable isn't used
141
    VkDebugUtilsMessengerEXT *list;
142
};
143
144
struct loader_debug_report_callback_list {
145
    size_t capacity;
146
    uint32_t padding;  // count variable isn't used
147
    VkDebugReportCallbackEXT *list;
148
};
149
150
struct loader_name_value {
151
    char *name;
152
    char *value;
153
};
154
155
struct loader_layer_functions {
156
    char *str_gipa;
157
    char *str_gdpa;
158
    char *str_negotiate_interface;
159
    PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface;
160
    PFN_vkGetInstanceProcAddr get_instance_proc_addr;
161
    PFN_vkGetDeviceProcAddr get_device_proc_addr;
162
    PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr;
163
};
164
165
// This structure is used to store the json file version in a more manageable way.
166
typedef struct {
167
    uint16_t major;
168
    uint16_t minor;
169
    uint16_t patch;
170
} loader_api_version;
171
172
// Enumeration used to clearly identify reason for library load failure.
173
enum loader_layer_library_status {
174
    LOADER_LAYER_LIB_NOT_LOADED = 0,
175
176
    LOADER_LAYER_LIB_SUCCESS_LOADED = 1,
177
178
    LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE = 20,
179
    LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD = 21,
180
    LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY = 22,
181
    LOADER_LAYER_LIB_ERROR_NEGOTIATE_INTERFACE_VERSION_FAILED = 23,
182
    LOADER_LAYER_LIB_ERROR_UNABLE_TO_FIND_VK_GET_INSTANCE_PROC_ADDR = 24,
183
};
184
185
enum layer_type_flags {
186
    VK_LAYER_TYPE_FLAG_NONE = 0x0,
187
    VK_LAYER_TYPE_FLAG_INSTANCE_LAYER = 0x1,  // If not set, indicates Device layer
188
    VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER = 0x2,  // If not set, indicates Implicit layer
189
    VK_LAYER_TYPE_FLAG_META_LAYER = 0x4,      // If not set, indicates standard layer
190
};
191
192
enum loader_layer_enabled_by_what {
193
    ENABLED_BY_WHAT_UNSET,  // default value indicates this field hasn't been filled in
194
    ENABLED_BY_WHAT_LOADER_SETTINGS_FILE,
195
    ENABLED_BY_WHAT_IMPLICIT_LAYER,
196
    ENABLED_BY_WHAT_VK_INSTANCE_LAYERS,
197
    ENABLED_BY_WHAT_VK_LOADER_LAYERS_ENABLE,
198
    ENABLED_BY_WHAT_IN_APPLICATION_API,
199
    ENABLED_BY_WHAT_META_LAYER,
200
};
201
202
struct loader_layer_properties {
203
    VkLayerProperties info;
204
    enum layer_type_flags type_flags;
205
    enum loader_settings_layer_control settings_control_value;
206
207
    uint32_t interface_version;  // PFN_vkNegotiateLoaderLayerInterfaceVersion
208
    char *manifest_file_name;
209
    char *lib_name;
210
    enum loader_layer_library_status lib_status;
211
    enum loader_layer_enabled_by_what enabled_by_what;
212
    loader_platform_dl_handle lib_handle;
213
    struct loader_layer_functions functions;
214
    struct loader_extension_list instance_extension_list;
215
    struct loader_device_extension_list device_extension_list;
216
    struct loader_name_value disable_env_var;
217
    struct loader_name_value enable_env_var;
218
    struct loader_string_list component_layer_names;
219
    struct {
220
        char *enumerate_instance_extension_properties;
221
        char *enumerate_instance_layer_properties;
222
        char *enumerate_instance_version;
223
    } pre_instance_functions;
224
    struct loader_string_list override_paths;
225
    bool is_override;
226
    bool keep;
227
    // Set while this meta-layer is being expanded, used to break cyclic component references.
228
    bool is_being_expanded;
229
    struct loader_string_list blacklist_layer_names;
230
    struct loader_string_list app_key_paths;
231
};
232
233
// Stores a list of loader_layer_properties
234
struct loader_layer_list {
235
    size_t capacity;
236
    uint32_t count;
237
    struct loader_layer_properties *list;
238
};
239
240
// Stores a list of pointers to loader_layer_properties
241
// Used for expanded_activated_layer_list
242
struct loader_pointer_layer_list {
243
    size_t capacity;
244
    uint32_t count;
245
    struct loader_layer_properties **list;
246
};
247
248
typedef VkResult(VKAPI_PTR *PFN_vkDevExt)(VkDevice device);
249
250
struct loader_dev_dispatch_table {
251
    VkLayerDispatchTable core_dispatch;
252
    PFN_vkDevExt ext_dispatch[MAX_NUM_UNKNOWN_EXTS];
253
    struct loader_device_terminator_dispatch extension_terminator_dispatch;
254
};
255
256
// per CreateDevice structure
257
struct loader_device {
258
    struct loader_dev_dispatch_table loader_dispatch;
259
    VkDevice chain_device;  // device object from the dispatch chain
260
    VkDevice icd_device;    // device object from the icd
261
    struct loader_physical_device_term *phys_dev_term;
262
263
    VkAllocationCallbacks alloc_callbacks;
264
265
    // List of activated device extensions that layers support (but not necessarily the driver which have functions that require
266
    // trampolines to work correctly. EX - vkDebugMarkerSetObjectNameEXT can name wrapped handles like instance, physical device,
267
    // or surface
268
    struct {
269
        bool ext_debug_marker_enabled;
270
        bool ext_debug_utils_enabled;
271
    } layer_extensions;
272
273
    // List of activated device extensions that have terminators implemented in the loader
274
    struct {
275
        bool khr_swapchain_enabled;
276
        bool khr_display_swapchain_enabled;
277
        bool khr_device_group_enabled;
278
        bool ext_debug_marker_enabled;
279
        bool ext_debug_utils_enabled;
280
        bool ext_full_screen_exclusive_enabled;
281
    } driver_extensions;
282
283
    struct loader_device *next;
284
285
    // Makes vkGetDeviceProcAddr check if core functions are supported by the current app_api_version.
286
    // Only set to true if VK_KHR_maintenance5 is enabled.
287
    bool should_ignore_device_commands_from_newer_version;
288
};
289
290
// Per ICD information
291
292
// Per ICD structure
293
struct loader_icd_term {
294
    // pointers to find other structs
295
    const struct loader_scanned_icd *scanned_icd;
296
    const struct loader_instance *this_instance;
297
    struct loader_device *logical_device_list;
298
    VkInstance instance;  // instance object from the icd
299
    struct loader_icd_term_dispatch dispatch;
300
301
    struct loader_icd_term *next;
302
303
    PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
304
305
    struct loader_instance_extension_enable_list enabled_instance_extensions;
306
307
    uint32_t physical_device_count;
308
309
    struct loader_surface_list surface_list;
310
    struct loader_debug_utils_messenger_list debug_utils_messenger_list;
311
    struct loader_debug_report_callback_list debug_report_callback_list;
312
};
313
314
// Per ICD library structure
315
struct loader_icd_tramp_list {
316
    size_t capacity;
317
    uint32_t count;
318
    struct loader_scanned_icd *scanned_list;
319
};
320
321
struct loader_instance_dispatch_table {
322
    VkLayerInstanceDispatchTable layer_inst_disp;  // must be first entry in structure
323
324
    // Physical device functions unknown to the loader
325
    PFN_PhysDevExt phys_dev_ext[MAX_NUM_UNKNOWN_EXTS];
326
};
327
328
// Unique magic number identifier for the loader.
329
0
#define LOADER_MAGIC_NUMBER 0x10ADED010110ADEDUL
330
331
// Per instance structure
332
// NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding): members are intentionally grouped by usage, not by size
333
struct loader_instance {
334
    struct loader_instance_dispatch_table *disp;  // must be first entry in structure
335
    uint64_t magic;                               // Should be LOADER_MAGIC_NUMBER
336
337
    // Store all the terminators for instance functions in case a layer queries one *after* vkCreateInstance
338
    VkLayerInstanceDispatchTable terminator_dispatch;
339
340
    // Vulkan API version the app is intending to use.
341
    loader_api_version app_api_version;
342
343
    // We need to manually track physical devices over time.  If the user
344
    // re-queries the information, we don't want to delete old data or
345
    // create new data unless necessary.
346
    uint32_t total_gpu_count;
347
    uint32_t phys_dev_count_term;
348
    struct loader_physical_device_term **phys_devs_term;
349
    uint32_t phys_dev_count_tramp;
350
    struct loader_physical_device_tramp **phys_devs_tramp;
351
352
    // We also need to manually track physical device groups, but we don't need
353
    // loader specific structures since we have that content in the physical
354
    // device stored internal to the public structures.
355
    uint32_t phys_dev_group_count_term;
356
    struct VkPhysicalDeviceGroupProperties **phys_dev_groups_term;
357
358
    struct loader_instance *next;
359
360
    uint32_t icd_terms_count;
361
    struct loader_icd_term *icd_terms;
362
    struct loader_icd_tramp_list icd_tramp_list;
363
364
    // Must store the strings inside loader_instance directly - since the asm code will offset into
365
    // loader_instance to get the function name
366
    uint32_t dev_ext_disp_function_count;
367
    char *dev_ext_disp_functions[MAX_NUM_UNKNOWN_EXTS];
368
    uint32_t phys_dev_ext_disp_function_count;
369
    char *phys_dev_ext_disp_functions[MAX_NUM_UNKNOWN_EXTS];
370
371
    struct loader_msg_callback_map_entry *icd_msg_callback_map;
372
373
    struct loader_string_list enabled_layer_names;
374
375
    struct loader_layer_list instance_layer_list;
376
    bool override_layer_present;
377
378
    // List of activated layers, including the layers enabled from expanding meta-layers into their individual component
379
    // layers. This active list of layers can include layers that failed to actually be enabled, such as not being able to load the
380
    // binary, failing version negotiation, and not being able to query vkGetInstanceProcAddr
381
    struct loader_pointer_layer_list expanded_activated_layer_list;
382
383
    VkInstance instance;  // layers/ICD instance returned to trampoline
384
385
    struct loader_extension_list ext_list;  // icds and loaders extensions
386
    struct loader_instance_extension_enable_list enabled_extensions;
387
388
    // Indicates which indices in the array are in-use and which are free to be reused
389
    struct loader_used_object_list surfaces_list;
390
    struct loader_used_object_list debug_utils_messengers_list;
391
    struct loader_used_object_list debug_report_callbacks_list;
392
393
    // Stores debug callbacks - used in the log.
394
    VkLayerDbgFunctionNode *current_dbg_function_head;        // Current head
395
    VkLayerDbgFunctionNode *instance_only_dbg_function_head;  // Only used for instance create/destroy
396
397
    VkAllocationCallbacks alloc_callbacks;
398
399
    // Set to true after vkCreateInstance has returned - necessary for loader_gpa_instance_terminator()
400
    bool instance_finished_creation;
401
402
    loader_settings settings;
403
404
    bool portability_enumeration_enabled;
405
406
    bool create_terminator_invalid_extension;
407
    bool supports_get_dev_prop_2;
408
};
409
410
// VkPhysicalDevice requires special treatment by loader.  Firstly, terminator
411
// code must be able to get the struct loader_icd_term to call into the proper
412
// driver  (multiple ICD/gpu case). This can be accomplished by wrapping the
413
// created VkPhysicalDevice in loader terminate_EnumeratePhysicalDevices().
414
// Secondly, the loader must be able to handle wrapped by layer VkPhysicalDevice
415
// in trampoline code.  This implies, that the loader trampoline code must also
416
// wrap the VkPhysicalDevice object in trampoline code.  Thus, loader has to
417
// wrap the VkPhysicalDevice created object twice. In trampoline code it can't
418
// rely on the terminator object wrapping since a layer may also wrap. Since
419
// trampoline code wraps the VkPhysicalDevice this means all loader trampoline
420
// code that passes a VkPhysicalDevice should unwrap it.
421
422
// Unique identifier for physical devices
423
0
#define PHYS_TRAMP_MAGIC_NUMBER 0x10ADED020210ADEDUL
424
425
// Per enumerated PhysicalDevice structure, used to wrap in trampoline code and
426
// also same structure used to wrap in terminator code
427
struct loader_physical_device_tramp {
428
    struct loader_instance_dispatch_table *disp;  // must be first entry in structure
429
    struct loader_instance *this_instance;
430
    uint64_t magic;             // Should be PHYS_TRAMP_MAGIC_NUMBER
431
    VkPhysicalDevice phys_dev;  // object from layers/loader terminator
432
};
433
434
// Per enumerated PhysicalDevice structure, used to wrap in terminator code
435
struct loader_physical_device_term {
436
    struct loader_instance_dispatch_table *disp;  // must be first entry in structure
437
    struct loader_icd_term *this_icd_term;
438
    VkPhysicalDevice phys_dev;  // object from ICD
439
};
440
441
#if defined(LOADER_ENABLE_LINUX_SORT)
442
// Structure for storing the relevant device information for selecting a device.
443
// NOTE: Needs to be defined here so we can store this content in the term structure
444
//       for quicker sorting.
445
struct LinuxSortedDeviceInfo {
446
    // Associated Vulkan Physical Device
447
    VkPhysicalDevice physical_device;
448
    bool default_device;
449
450
    // Loader specific items about the driver providing support for this physical device
451
    struct loader_icd_term *icd_term;
452
453
    // Some generic device properties
454
    VkPhysicalDeviceType device_type;
455
    char device_name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE];
456
    uint32_t vendor_id;
457
    uint32_t device_id;
458
459
    // PCI information on this device
460
    bool has_pci_bus_info;
461
    uint32_t pci_domain;
462
    uint32_t pci_bus;
463
    uint32_t pci_device;
464
    uint32_t pci_function;
465
};
466
#endif  // LOADER_ENABLE_LINUX_SORT
467
468
// Per enumerated PhysicalDeviceGroup structure, used to wrap in terminator code
469
struct loader_physical_device_group_term {
470
    struct loader_icd_term *this_icd_term;
471
    VkPhysicalDeviceGroupProperties group_props;
472
#if defined(LOADER_ENABLE_LINUX_SORT)
473
    struct LinuxSortedDeviceInfo internal_device_info[VK_MAX_DEVICE_GROUP_SIZE];
474
#endif  // LOADER_ENABLE_LINUX_SORT
475
};
476
477
struct loader_struct {
478
    struct loader_instance *instances;
479
};
480
481
struct loader_scanned_icd {
482
    char *lib_name;
483
    loader_platform_dl_handle handle;
484
    uint32_t api_version;
485
    uint32_t interface_version;
486
    PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
487
    PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;
488
    PFN_vkCreateInstance CreateInstance;
489
    PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
490
#if defined(VK_USE_PLATFORM_WIN32_KHR)
491
    PFN_vk_icdEnumerateAdapterPhysicalDevices EnumerateAdapterPhysicalDevices;
492
#endif
493
};
494
495
enum loader_data_files_type {
496
    LOADER_DATA_FILE_MANIFEST_DRIVER = 0,
497
    LOADER_DATA_FILE_MANIFEST_EXPLICIT_LAYER,
498
    LOADER_DATA_FILE_MANIFEST_IMPLICIT_LAYER,
499
    LOADER_DATA_FILE_NUM_TYPES  // Not a real field, used for possible loop terminator
500
};
501
502
struct loader_icd_physical_devices {
503
    uint32_t device_count;
504
    VkPhysicalDevice *physical_devices;
505
    struct loader_icd_term *icd_term;
506
#if defined(WIN32)
507
    LUID windows_adapter_luid;
508
#endif
509
};
510
511
struct loader_msg_callback_map_entry {
512
    VkDebugReportCallbackEXT icd_obj;
513
    VkDebugReportCallbackEXT loader_obj;
514
};
515
516
typedef enum loader_filter_string_type {
517
    FILTER_STRING_FULLNAME = 0,
518
    FILTER_STRING_SUBSTRING,
519
    FILTER_STRING_PREFIX,
520
    FILTER_STRING_SUFFIX,
521
    FILTER_STRING_SPECIAL,
522
} loader_filter_string_type;
523
524
struct loader_envvar_filter_value {
525
    char value[VK_MAX_EXTENSION_NAME_SIZE];
526
    size_t length;
527
    loader_filter_string_type type;
528
};
529
530
0
#define MAX_ADDITIONAL_FILTERS 16
531
struct loader_envvar_filter {
532
    uint32_t count;
533
    struct loader_envvar_filter_value filters[MAX_ADDITIONAL_FILTERS];
534
};
535
struct loader_envvar_disable_layers_filter {
536
    struct loader_envvar_filter additional_filters;
537
    bool disable_all;
538
    bool disable_all_implicit;
539
    bool disable_all_explicit;
540
};
541
542
struct loader_envvar_all_filters {
543
    struct loader_envvar_filter enable_filter;
544
    struct loader_envvar_disable_layers_filter disable_filter;
545
    struct loader_envvar_filter allow_filter;
546
};
547
548
struct loader_envvar_id_filter_value {
549
    uint32_t begin;
550
    uint32_t end;
551
};
552
553
struct loader_envvar_id_filter {
554
    uint32_t count;
555
    struct loader_envvar_id_filter_value *filters;
556
};