From 80a36ff985b7fccc8590d6b07e4f2a2f36585f8f Mon Sep 17 00:00:00 2001 From: sakrel <2487152+sakrel@users.noreply.github.com> Date: Sat, 12 Aug 2023 14:56:49 +0200 Subject: [PATCH] Add support for GLSL source-level debugging with RenderDoc (`--generate-spirv-debug-info`) --- core/config/engine.cpp | 4 ++++ core/config/engine.h | 2 ++ drivers/vulkan/vulkan_context.cpp | 4 ++++ main/main.cpp | 3 +++ modules/glslang/register_types.cpp | 30 ++++++++++++------------------ 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/core/config/engine.cpp b/core/config/engine.cpp index 7fdea7d1aa2..6727c58fd11 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -239,6 +239,10 @@ bool Engine::is_validation_layers_enabled() const { return use_validation_layers; } +bool Engine::is_generate_spirv_debug_info_enabled() const { + return generate_spirv_debug_info; +} + void Engine::set_print_error_messages(bool p_enabled) { CoreGlobals::print_error_enabled = p_enabled; } diff --git a/core/config/engine.h b/core/config/engine.h index 5ea653ba6cd..73d40d50ae4 100644 --- a/core/config/engine.h +++ b/core/config/engine.h @@ -67,6 +67,7 @@ private: double _physics_interpolation_fraction = 0.0f; bool abort_on_gpu_errors = false; bool use_validation_layers = false; + bool generate_spirv_debug_info = false; int32_t gpu_idx = -1; uint64_t _process_frames = 0; @@ -156,6 +157,7 @@ public: bool is_abort_on_gpu_errors_enabled() const; bool is_validation_layers_enabled() const; + bool is_generate_spirv_debug_info_enabled() const; int32_t get_gpu_index() const; Engine(); diff --git a/drivers/vulkan/vulkan_context.cpp b/drivers/vulkan/vulkan_context.cpp index c167caeb7cf..4b18a500e1d 100644 --- a/drivers/vulkan/vulkan_context.cpp +++ b/drivers/vulkan/vulkan_context.cpp @@ -504,6 +504,10 @@ Error VulkanContext::_initialize_device_extensions() { register_requested_device_extension(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME, false); register_requested_device_extension(VK_KHR_MAINTENANCE_2_EXTENSION_NAME, false); + if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) { + register_requested_device_extension(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME, true); + } + // TODO consider the following extensions: // - VK_KHR_spirv_1_4 // - VK_KHR_swapchain_mutable_format diff --git a/main/main.cpp b/main/main.cpp index 220afda5def..f79a71474dc 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -458,6 +458,7 @@ void Main::print_help(const char *p_binary) { #if DEBUG_ENABLED OS::get_singleton()->print(" --gpu-abort Abort on graphics API usage errors (usually validation layer errors). May help see the problem if your system freezes.\n"); #endif + OS::get_singleton()->print(" --generate-spirv-debug-info Generate SPIR-V debug information. This allows source-level shader debugging with RenderDoc.\n"); OS::get_singleton()->print(" --remote-debug Remote debug (://[:], e.g. tcp://127.0.0.1:6007).\n"); OS::get_singleton()->print(" --single-threaded-scene Scene tree runs in single-threaded mode. Sub-thread groups are disabled and run on the main thread.\n"); #if defined(DEBUG_ENABLED) @@ -1019,6 +1020,8 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph } else if (I->get() == "--gpu-abort") { Engine::singleton->abort_on_gpu_errors = true; #endif + } else if (I->get() == "--generate-spirv-debug-info") { + Engine::singleton->generate_spirv_debug_info = true; } else if (I->get() == "--tablet-driver") { if (I->next()) { tablet_driver = I->next()->get(); diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp index 622910761d3..2b070c24b88 100644 --- a/modules/glslang/register_types.cpp +++ b/modules/glslang/register_types.cpp @@ -32,6 +32,7 @@ #include "glslang_resource_limits.h" +#include "core/config/engine.h" #include "servers/rendering/rendering_device.h" #include @@ -56,7 +57,6 @@ static Vector _compile_shader_glsl(RenderingDevice::ShaderStage p_stage glslang::EShTargetClientVersion ClientVersion = glslang::EShTargetVulkan_1_2; glslang::EShTargetLanguageVersion TargetVersion = glslang::EShTargetSpv_1_5; - glslang::TShader::ForbidIncluder includer; if (capabilities->device_family == RenderingDevice::DeviceFamily::DEVICE_VULKAN) { if (capabilities->version_major == 1 && capabilities->version_minor == 0) { @@ -127,23 +127,10 @@ static Vector _compile_shader_glsl(RenderingDevice::ShaderStage p_stage } EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules); - const int DefaultVersion = 100; - std::string pre_processed_code; - - //preprocess - if (!shader.preprocess(&DefaultTBuiltInResource, DefaultVersion, ENoProfile, false, false, messages, &pre_processed_code, includer)) { - if (r_error) { - (*r_error) = "Failed pre-process:\n"; - (*r_error) += shader.getInfoLog(); - (*r_error) += "\n"; - (*r_error) += shader.getInfoDebugLog(); - } - - return ret; + if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) { + messages = (EShMessages)(messages | EShMsgDebugInfo); } - //set back.. - cs_strings = pre_processed_code.c_str(); - shader.setStrings(&cs_strings, 1); + const int DefaultVersion = 100; //parse if (!shader.parse(&DefaultTBuiltInResource, DefaultVersion, false, messages)) { @@ -174,6 +161,13 @@ static Vector _compile_shader_glsl(RenderingDevice::ShaderStage p_stage std::vector SpirV; spv::SpvBuildLogger logger; glslang::SpvOptions spvOptions; + + if (Engine::get_singleton()->is_generate_spirv_debug_info_enabled()) { + spvOptions.generateDebugInfo = true; + spvOptions.emitNonSemanticShaderDebugInfo = true; + spvOptions.emitNonSemanticShaderDebugSource = true; + } + glslang::GlslangToSpv(*program.getIntermediate(stages[p_stage]), SpirV, &logger, &spvOptions); ret.resize(SpirV.size() * sizeof(uint32_t)); @@ -188,7 +182,7 @@ static Vector _compile_shader_glsl(RenderingDevice::ShaderStage p_stage static String _get_cache_key_function_glsl(const RenderingDevice *p_render_device) { const RD::Capabilities *capabilities = p_render_device->get_device_capabilities(); String version; - version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities->version_major) + ", minor=" + itos(capabilities->version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)); + version = "SpirVGen=" + itos(glslang::GetSpirvGeneratorVersion()) + ", major=" + itos(capabilities->version_major) + ", minor=" + itos(capabilities->version_minor) + " , subgroup_size=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_SIZE)) + " , subgroup_ops=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_OPERATIONS)) + " , subgroup_in_shaders=" + itos(p_render_device->limit_get(RD::LIMIT_SUBGROUP_IN_SHADERS)) + " , debug=" + itos(Engine::get_singleton()->is_generate_spirv_debug_info_enabled()); return version; }