diff --git a/src/common/config.cpp b/src/common/config.cpp index b7d99bbf..0d117c21 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -21,6 +21,8 @@ static bool isShowSplash = false; static bool isNullGpu = false; static bool shouldDumpShaders = false; static bool shouldDumpPM4 = false; +static bool vkValidation = false; +static bool vkValidationSync = false; bool isLleLibc() { return isLibc; @@ -69,6 +71,14 @@ bool dumpPM4() { return shouldDumpPM4; } +bool vkValidationEnabled() { + return vkValidation; +} + +bool vkValidationSyncEnabled() { + return vkValidationSync; +} + void load(const std::filesystem::path& path) { // If the configuration file does not exist, create it and return std::error_code error; @@ -110,6 +120,15 @@ void load(const std::filesystem::path& path) { shouldDumpPM4 = toml::find_or(gpu, "dumpPM4", false); } } + if (data.contains("Vulkan")) { + const auto vkResult = toml::expect(data.at("Vulkan")); + if (vkResult.is_ok()) { + auto vk = vkResult.unwrap(); + + vkValidation = toml::find_or(vk, "validation", true); + vkValidationSync = toml::find_or(vk, "validation_sync", true); + } + } if (data.contains("Debug")) { auto debugResult = toml::expect(data.at("Debug")); if (debugResult.is_ok()) { @@ -156,6 +175,8 @@ void save(const std::filesystem::path& path) { data["GPU"]["nullGpu"] = isNullGpu; data["GPU"]["dumpShaders"] = shouldDumpShaders; data["GPU"]["dumpPM4"] = shouldDumpPM4; + data["Vulkan"]["validation"] = vkValidation; + data["Vulkan"]["validation_sync"] = vkValidationSync; data["Debug"]["DebugDump"] = isDebugDump; data["LLE"]["libc"] = isLibc; diff --git a/src/common/config.h b/src/common/config.h index 53925379..8da3c6de 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -25,4 +25,7 @@ bool nullGpu(); bool dumpShaders(); bool dumpPM4(); +bool vkValidationEnabled(); +bool vkValidationSyncEnabled(); + }; // namespace Config diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 72ee6c9b..572316af 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -62,8 +62,8 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for } RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool) - : window{window_}, instance{window, Config::getGpuId()}, scheduler{instance}, - swapchain{instance, window}, texture_cache{instance, scheduler} { + : window{window_}, instance{window, Config::getGpuId(), Config::vkValidationEnabled()}, + scheduler{instance}, swapchain{instance, window}, texture_cache{instance, scheduler} { rasterizer = std::make_unique(instance, scheduler, texture_cache, liverpool); const u32 num_images = swapchain.GetImageCount(); const vk::Device device = instance.GetDevice(); diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index dc10ec6c..355d2603 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -40,10 +40,13 @@ Instance::Instance(bool enable_validation, bool dump_command_buffers) dump_command_buffers)}, physical_devices{instance->enumeratePhysicalDevices()} {} -Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index) - : instance{CreateInstance(dl, window.getWindowInfo().type, true, false)}, - debug_callback{CreateDebugCallback(*instance)}, +Instance::Instance(Frontend::WindowSDL& window, s32 physical_device_index, + bool enable_validation /*= false*/) + : instance{CreateInstance(dl, window.getWindowInfo().type, enable_validation, false)}, physical_devices{instance->enumeratePhysicalDevices()} { + if (enable_validation) { + debug_callback = CreateDebugCallback(*instance); + } const std::size_t num_physical_devices = static_cast(physical_devices.size()); ASSERT_MSG(num_physical_devices > 0, "No physical devices found"); diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index 28af5405..797eb886 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -18,7 +18,8 @@ namespace Vulkan { class Instance { public: explicit Instance(bool validation = false, bool dump_command_buffers = false); - explicit Instance(Frontend::WindowSDL& window, s32 physical_device_index); + explicit Instance(Frontend::WindowSDL& window, s32 physical_device_index, + bool enable_validation = false); ~Instance(); /// Returns a formatted string for the driver version @@ -200,7 +201,7 @@ private: vk::PhysicalDeviceProperties properties; vk::PhysicalDeviceFeatures features; vk::DriverIdKHR driver_id; - vk::UniqueDebugUtilsMessengerEXT debug_callback; + vk::UniqueDebugUtilsMessengerEXT debug_callback{}; std::string vendor_name; VmaAllocator allocator{}; vk::Queue present_queue; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 3a14a02e..11cd5419 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -170,12 +170,7 @@ std::unique_ptr PipelineCache::CreateGraphicsPipeline() { // Set module name to hash in renderdoc const auto name = fmt::format("{}_{:#x}", stage, hash); - const vk::DebugUtilsObjectNameInfoEXT name_info = { - .objectType = vk::ObjectType::eShaderModule, - .objectHandle = std::bit_cast(stages[i]), - .pObjectName = name.c_str(), - }; - instance.GetDevice().setDebugUtilsObjectNameEXT(name_info); + Vulkan::SetObjectName(instance.GetDevice(), stages[i], name); if (Config::dumpShaders()) { DumpShader(spv_code, hash, stage, "spv"); diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index 5cc890f6..90b3f4a8 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -15,12 +15,16 @@ #include #include "common/assert.h" +#include "common/config.h" #include "common/logging/log.h" #include "sdl_window.h" #include "video_core/renderer_vulkan/vk_platform.h" namespace Vulkan { +static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation"; +static const char* const API_DUMP_LAYER_NAME = "VK_LAYER_LUNARG_api_dump"; + static VKAPI_ATTR VkBool32 VKAPI_CALL DebugUtilsCallback( VkDebugUtilsMessageSeverityFlagBitsEXT severity, VkDebugUtilsMessageTypeFlagsEXT type, const VkDebugUtilsMessengerCallbackDataEXT* callback_data, void* user_data) { @@ -179,7 +183,7 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT VK_VERSION_MAJOR(available_version), VK_VERSION_MINOR(available_version))); } - const auto extensions = GetInstanceExtensions(window_type, enable_validation); + const auto extensions = GetInstanceExtensions(window_type, true); const vk::ApplicationInfo application_info = { .pApplicationName = "shadPS4", @@ -193,21 +197,37 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT std::array layers; if (enable_validation) { - layers[num_layers++] = "VK_LAYER_KHRONOS_validation"; + layers[num_layers++] = VALIDATION_LAYER_NAME; } if (dump_command_buffers) { - layers[num_layers++] = "VK_LAYER_LUNARG_api_dump"; + layers[num_layers++] = API_DUMP_LAYER_NAME; } - vk::InstanceCreateInfo instance_ci = { - .pApplicationInfo = &application_info, - .enabledLayerCount = num_layers, - .ppEnabledLayerNames = layers.data(), - .enabledExtensionCount = static_cast(extensions.size()), - .ppEnabledExtensionNames = extensions.data(), + vk::Bool32 enable_sync = + enable_validation && Config::vkValidationSyncEnabled() ? vk::True : vk::False; + vk::LayerSettingEXT layer_set = { + .pLayerName = VALIDATION_LAYER_NAME, + .pSettingName = "validate_sync", + .type = vk::LayerSettingTypeEXT::eBool32, + .valueCount = 1, + .pValues = &enable_sync, }; - auto instance = vk::createInstanceUnique(instance_ci); + vk::StructureChain instance_ci_chain = { + vk::InstanceCreateInfo{ + .pApplicationInfo = &application_info, + .enabledLayerCount = num_layers, + .ppEnabledLayerNames = layers.data(), + .enabledExtensionCount = static_cast(extensions.size()), + .ppEnabledExtensionNames = extensions.data(), + }, + vk::LayerSettingsCreateInfoEXT{ + .settingCount = 1, + .pSettings = &layer_set, + }, + }; + + auto instance = vk::createInstanceUnique(instance_ci_chain.get()); VULKAN_HPP_DEFAULT_DISPATCHER.init(*instance); diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index 29f27f15..3fff9c11 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -222,12 +222,7 @@ TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& sc // Set module debug name auto module_name = magic_enum::enum_name(static_cast(pl_id)); - const vk::DebugUtilsObjectNameInfoEXT name_info = { - .objectType = vk::ObjectType::eShaderModule, - .objectHandle = std::bit_cast(module), - .pObjectName = module_name.data(), - }; - instance.GetDevice().setDebugUtilsObjectNameEXT(name_info); + Vulkan::SetObjectName(instance.GetDevice(), module, module_name); const vk::PipelineShaderStageCreateInfo shader_ci = { .stage = vk::ShaderStageFlagBits::eCompute,