diff --git a/include/private/vkd3d_debug.h b/include/private/vkd3d_debug.h index 418e2c45..7642dec5 100644 --- a/include/private/vkd3d_debug.h +++ b/include/private/vkd3d_debug.h @@ -22,6 +22,7 @@ #include "vkd3d_common.h" #include +#include #ifdef VKD3D_NO_TRACE_MESSAGES #define TRACE(args...) do { } while (0) @@ -90,4 +91,13 @@ static inline const char *debugstr_guid(const GUID *guid) unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value) DECLSPEC_HIDDEN; +struct vkd3d_debug_option +{ + const char *name; + uint64_t flag; +}; + +uint64_t vkd3d_parse_debug_options(const char *string, + const struct vkd3d_debug_option *options, unsigned int option_count) DECLSPEC_HIDDEN; + #endif /* __VKD3D_DEBUG_H */ diff --git a/libs/vkd3d-common/debug.c b/libs/vkd3d-common/debug.c index 6b9662bb..9a27c22e 100644 --- a/libs/vkd3d-common/debug.c +++ b/libs/vkd3d-common/debug.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #define VKD3D_DEBUG_BUFFER_COUNT 64 @@ -316,3 +317,41 @@ unsigned int vkd3d_env_var_as_uint(const char *name, unsigned int default_value) return default_value; } + +static bool is_option_separator(char c) +{ + return c == ',' || c == ';' || c == '\0'; +} + +uint64_t vkd3d_parse_debug_options(const char *string, + const struct vkd3d_debug_option *options, unsigned int option_count) +{ + char prev_char, next_char; + uint64_t flags = 0; + unsigned int i; + const char *p; + + for (i = 0; i < option_count; ++i) + { + const struct vkd3d_debug_option *opt = &options[i]; + + p = string; + while (p) + { + if ((p = strstr(p, opt->name))) + { + prev_char = p > string ? p[-1] : 0; + p += strlen(opt->name); + next_char = *p; + + if (is_option_separator(prev_char) && is_option_separator(next_char)) + { + flags |= opt->flag; + break; + } + } + } + } + + return flags; +} diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index 06455798..052d4f6f 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -172,25 +172,19 @@ static bool is_extension_disabled(const char *extension_name) } static bool has_extension(const VkExtensionProperties *extensions, - unsigned int count, const char *extension_name, bool is_debug_only) + unsigned int count, const char *extension_name) { unsigned int i; for (i = 0; i < count; ++i) { - if (strcmp(extensions[i].extensionName, extension_name)) - continue; if (is_extension_disabled(extension_name)) { WARN("Extension %s is disabled.\n", debugstr_a(extension_name)); continue; } - if (is_debug_only && vkd3d_dbg_get_level() < VKD3D_DBG_LEVEL_WARN) - { - TRACE("Skipping debug-only extension %s.\n", debugstr_a(extension_name)); - continue; - } - return true; + if (!strcmp(extensions[i].extensionName, extension_name)) + return true; } return false; } @@ -200,14 +194,15 @@ static unsigned int vkd3d_check_extensions(const VkExtensionProperties *extensio const struct vkd3d_optional_extension_info *optional_extensions, unsigned int optional_extension_count, const char * const *user_extensions, unsigned int user_extension_count, const char * const *optional_user_extensions, unsigned int optional_user_extension_count, - bool *user_extension_supported, struct vkd3d_vulkan_info *vulkan_info, const char *extension_type) + bool *user_extension_supported, struct vkd3d_vulkan_info *vulkan_info, const char *extension_type, + bool is_debug_enabled) { unsigned int extension_count = 0; unsigned int i; for (i = 0; i < required_extension_count; ++i) { - if (!has_extension(extensions, count, required_extensions[i], false)) + if (!has_extension(extensions, count, required_extensions[i])) ERR("Required %s extension %s is not supported.\n", extension_type, debugstr_a(required_extensions[i])); ++extension_count; @@ -217,10 +212,16 @@ static unsigned int vkd3d_check_extensions(const VkExtensionProperties *extensio { const char *extension_name = optional_extensions[i].extension_name; ptrdiff_t offset = optional_extensions[i].vulkan_info_offset; - bool is_debug_only = optional_extensions[i].is_debug_only; bool *supported = (void *)((uintptr_t)vulkan_info + offset); - if ((*supported = has_extension(extensions, count, extension_name, is_debug_only))) + if (!is_debug_enabled && optional_extensions[i].is_debug_only) + { + *supported = false; + TRACE("Skipping debug-only extension %s.\n", debugstr_a(extension_name)); + continue; + } + + if ((*supported = has_extension(extensions, count, extension_name))) { TRACE("Found %s extension.\n", debugstr_a(extension_name)); ++extension_count; @@ -229,7 +230,7 @@ static unsigned int vkd3d_check_extensions(const VkExtensionProperties *extensio for (i = 0; i < user_extension_count; ++i) { - if (!has_extension(extensions, count, user_extensions[i], false)) + if (!has_extension(extensions, count, user_extensions[i])) ERR("Required user %s extension %s is not supported.\n", extension_type, debugstr_a(user_extensions[i])); ++extension_count; @@ -238,7 +239,7 @@ static unsigned int vkd3d_check_extensions(const VkExtensionProperties *extensio assert(!optional_user_extension_count || user_extension_supported); for (i = 0; i < optional_user_extension_count; ++i) { - if (has_extension(extensions, count, optional_user_extensions[i], false)) + if (has_extension(extensions, count, optional_user_extensions[i])) { user_extension_supported[i] = true; ++extension_count; @@ -360,7 +361,8 @@ static HRESULT vkd3d_init_instance_caps(struct vkd3d_instance *instance, create_info->instance_extensions, create_info->instance_extension_count, optional_extensions ? optional_extensions->extensions : NULL, optional_extensions ? optional_extensions->extension_count : 0, - *user_extension_supported, vulkan_info, "instance"); + *user_extension_supported, vulkan_info, "instance", + instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG); vkd3d_free(vk_extensions); return S_OK; @@ -433,6 +435,25 @@ static void vkd3d_init_debug_report(struct vkd3d_instance *instance) instance->vk_debug_callback = callback; } +static const struct vkd3d_debug_option vkd3d_config_options[] = +{ + {"vk_debug", VKD3D_CONFIG_FLAG_VULKAN_DEBUG}, /* enable Vulkan debug extensions */ +}; + +static uint64_t vkd3d_init_config_flags(void) +{ + uint64_t config_flags; + const char *config; + + config = getenv("VKD3D_CONFIG"); + config_flags = vkd3d_parse_debug_options(config, vkd3d_config_options, ARRAY_SIZE(vkd3d_config_options)); + + if (config_flags) + TRACE("VKD3D_CONFIG='%s'.\n", config); + + return config_flags; +} + static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, const struct vkd3d_instance_create_info *create_info) { @@ -470,6 +491,8 @@ static HRESULT vkd3d_instance_init(struct vkd3d_instance *instance, instance->join_thread = create_info->pfn_join_thread; instance->wchar_size = create_info->wchar_size; + instance->config_flags = vkd3d_init_config_flags(); + if (FAILED(hr = vkd3d_init_vk_global_procs(instance, create_info->pfn_vkGetInstanceProcAddr))) { ERR("Failed to initialize Vulkan global procs, hr %#x.\n", hr); @@ -1250,7 +1273,8 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device, create_info->device_extensions, create_info->device_extension_count, optional_extensions ? optional_extensions->extensions : NULL, optional_extensions ? optional_extensions->extension_count : 0, - *user_extension_supported, vulkan_info, "device"); + *user_extension_supported, vulkan_info, "device", + device->vkd3d_instance->config_flags & VKD3D_CONFIG_FLAG_VULKAN_DEBUG); depth_clip_features = vk_find_struct(features2->pNext, PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT); if (depth_clip_features) diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index be82851a..b3331826 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -113,6 +113,11 @@ struct vkd3d_vulkan_info D3D_FEATURE_LEVEL max_feature_level; }; +enum vkd3d_config_flags +{ + VKD3D_CONFIG_FLAG_VULKAN_DEBUG = 0x00000001, +}; + struct vkd3d_instance { VkInstance vk_instance; @@ -127,6 +132,8 @@ struct vkd3d_instance struct vkd3d_vk_global_procs vk_global_procs; void *libvulkan; + uint64_t config_flags; + VkDebugReportCallbackEXT vk_debug_callback; LONG refcount;