diff options
| author | JMC47 <JMC4789@gmail.com> | 2022-07-08 15:29:58 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-08 15:29:58 -0400 |
| commit | 828afc67356c2299c6056d618eb6b7afe4c843b9 (patch) | |
| tree | cb7809cf9aad689968ec209e8d886b5457ca68dc /Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp | |
| parent | 7cc89f5642cab3b91aef1c8255af857a1607ddf6 (diff) | |
| parent | a8b52663479effc0f404f7c0f8b52bc0ee37b742 (diff) | |
Merge pull request #10673 from iwubcode/spirv-backends
D3D: Generate HLSL from SPIRV*
Diffstat (limited to 'Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp | 198 |
1 files changed, 16 insertions, 182 deletions
diff --git a/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp b/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp index c9adcc1bf7..fde89ca394 100644 --- a/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp +++ b/Source/Core/VideoBackends/Vulkan/ShaderCompiler.cpp @@ -4,36 +4,13 @@ #include "VideoBackends/Vulkan/ShaderCompiler.h" #include <cstddef> -#include <cstdlib> -#include <cstring> -#include <fstream> -#include <memory> #include <string> -// glslang includes -#include "GlslangToSpv.h" -#include "ResourceLimits.h" -#include "ShaderLang.h" -#include "disassemble.h" - -#include "Common/FileUtil.h" -#include "Common/Logging/Log.h" -#include "Common/MsgHandler.h" -#include "Common/StringUtil.h" -#include "Common/Version.h" - #include "VideoBackends/Vulkan/VulkanContext.h" -#include "VideoCommon/VideoBackendBase.h" -#include "VideoCommon/VideoConfig.h" +#include "VideoCommon/Spirv.h" namespace Vulkan::ShaderCompiler { -// Registers itself for cleanup via atexit -bool InitializeGlslang(); - -// Resource limits used when compiling shaders -static const TBuiltInResource* GetCompilerResourceLimits(); - // Regarding the UBO bind points, we subtract one from the binding index because // the OpenGL backend requires UBO #0 for non-block uniforms (at least on NV). // This allows us to share the same shaders but use bind point #0 in the Vulkan @@ -111,25 +88,9 @@ static const char SUBGROUP_HELPER_HEADER[] = R"( #define SUBGROUP_MAX(value) value = subgroupMax(value) )"; -static std::optional<SPIRVCodeVector> CompileShaderToSPV(EShLanguage stage, - const char* stage_filename, - std::string_view source, - std::string_view header) +static std::string GetShaderCode(std::string_view source, std::string_view header) { - if (!InitializeGlslang()) - return std::nullopt; - - std::unique_ptr<glslang::TShader> shader = std::make_unique<glslang::TShader>(stage); - std::unique_ptr<glslang::TProgram> program; - glslang::TShader::ForbidIncluder includer; - EProfile profile = ECoreProfile; - EShMessages messages = - static_cast<EShMessages>(EShMsgDefault | EShMsgSpvRules | EShMsgVulkanRules); - int default_version = 450; - std::string full_source_code; - const char* pass_source_code = source.data(); - int pass_source_code_length = static_cast<int>(source.size()); if (!header.empty()) { constexpr size_t subgroup_helper_header_length = std::size(SUBGROUP_HELPER_HEADER) - 1; @@ -138,168 +99,41 @@ static std::optional<SPIRVCodeVector> CompileShaderToSPV(EShLanguage stage, if (g_vulkan_context->SupportsShaderSubgroupOperations()) full_source_code.append(SUBGROUP_HELPER_HEADER, subgroup_helper_header_length); full_source_code.append(source); - pass_source_code = full_source_code.c_str(); - pass_source_code_length = static_cast<int>(full_source_code.length()); - } - - // Sub-group operations require Vulkan 1.1 and SPIR-V 1.3. - if (g_vulkan_context->SupportsShaderSubgroupOperations()) - shader->setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_3); - - shader->setStringsWithLengths(&pass_source_code, &pass_source_code_length, 1); - - auto DumpBadShader = [&](const char* msg) { - static int counter = 0; - std::string filename = VideoBackendBase::BadShaderFilename(stage_filename, counter++); - std::ofstream stream; - File::OpenFStream(stream, filename, std::ios_base::out); - if (stream.good()) - { - stream << full_source_code << std::endl; - stream << msg << std::endl; - stream << "Shader Info Log:" << std::endl; - stream << shader->getInfoLog() << std::endl; - stream << shader->getInfoDebugLog() << std::endl; - if (program) - { - stream << "Program Info Log:" << std::endl; - stream << program->getInfoLog() << std::endl; - stream << program->getInfoDebugLog() << std::endl; - } - } - - stream << "\n"; - stream << "Dolphin Version: " + Common::GetScmRevStr() + "\n"; - stream << "Video Backend: " + g_video_backend->GetDisplayName(); - stream.close(); - - PanicAlertFmt("{} (written to {})\nDebug info:\n{}", msg, filename, shader->getInfoLog()); - }; - - if (!shader->parse(GetCompilerResourceLimits(), default_version, profile, false, true, messages, - includer)) - { - DumpBadShader("Failed to parse shader"); - return std::nullopt; - } - - // Even though there's only a single shader, we still need to link it to generate SPV - program = std::make_unique<glslang::TProgram>(); - program->addShader(shader.get()); - if (!program->link(messages)) - { - DumpBadShader("Failed to link program"); - return std::nullopt; - } - - glslang::TIntermediate* intermediate = program->getIntermediate(stage); - if (!intermediate) - { - DumpBadShader("Failed to generate SPIR-V"); - return std::nullopt; - } - - SPIRVCodeVector out_code; - spv::SpvBuildLogger logger; - glslang::SpvOptions options; - - if (g_ActiveConfig.bEnableValidationLayer) - { - // Attach the source code to the SPIR-V for tools like RenderDoc. - intermediate->addSourceText(pass_source_code, pass_source_code_length); - - options.generateDebugInfo = true; - options.disableOptimizer = true; - options.optimizeSize = false; - options.disassemble = false; - options.validate = true; } - glslang::GlslangToSpv(*intermediate, out_code, &logger, &options); - - // Write out messages - // Temporary: skip if it contains "Warning, version 450 is not yet complete; most version-specific - // features are present, but some are missing." - if (strlen(shader->getInfoLog()) > 108) - WARN_LOG_FMT(VIDEO, "Shader info log: {}", shader->getInfoLog()); - if (strlen(shader->getInfoDebugLog()) > 0) - WARN_LOG_FMT(VIDEO, "Shader debug info log: {}", shader->getInfoDebugLog()); - if (strlen(program->getInfoLog()) > 25) - WARN_LOG_FMT(VIDEO, "Program info log: {}", program->getInfoLog()); - if (strlen(program->getInfoDebugLog()) > 0) - WARN_LOG_FMT(VIDEO, "Program debug info log: {}", program->getInfoDebugLog()); - const std::string spv_messages = logger.getAllMessages(); - if (!spv_messages.empty()) - WARN_LOG_FMT(VIDEO, "SPIR-V conversion messages: {}", spv_messages); - - // Dump source code of shaders out to file if enabled. - if (g_ActiveConfig.iLog & CONF_SAVESHADERS) - { - static int counter = 0; - std::string filename = StringFromFormat("%s%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), - stage_filename, counter++); - - std::ofstream stream; - File::OpenFStream(stream, filename, std::ios_base::out); - if (stream.good()) - { - stream << full_source_code << std::endl; - stream << "Shader Info Log:" << std::endl; - stream << shader->getInfoLog() << std::endl; - stream << shader->getInfoDebugLog() << std::endl; - stream << "Program Info Log:" << std::endl; - stream << program->getInfoLog() << std::endl; - stream << program->getInfoDebugLog() << std::endl; - stream << "SPIR-V conversion messages: " << std::endl; - stream << spv_messages; - stream << "SPIR-V:" << std::endl; - spv::Disassemble(stream, out_code); - } - } - - return out_code; + return full_source_code; } -bool InitializeGlslang() +static glslang::EShTargetLanguageVersion GetLanguageVersion() { - static bool glslang_initialized = false; - if (glslang_initialized) - return true; - - if (!glslang::InitializeProcess()) - { - PanicAlertFmt("Failed to initialize glslang shader compiler"); - return false; - } - - std::atexit([]() { glslang::FinalizeProcess(); }); - - glslang_initialized = true; - return true; -} + // Sub-group operations require Vulkan 1.1 and SPIR-V 1.3. + if (g_vulkan_context->SupportsShaderSubgroupOperations()) + return glslang::EShTargetSpv_1_3; -const TBuiltInResource* GetCompilerResourceLimits() -{ - return &glslang::DefaultTBuiltInResource; + return glslang::EShTargetSpv_1_0; } std::optional<SPIRVCodeVector> CompileVertexShader(std::string_view source_code) { - return CompileShaderToSPV(EShLangVertex, "vs", source_code, SHADER_HEADER); + return SPIRV::CompileVertexShader(GetShaderCode(source_code, SHADER_HEADER), APIType::Vulkan, + GetLanguageVersion()); } std::optional<SPIRVCodeVector> CompileGeometryShader(std::string_view source_code) { - return CompileShaderToSPV(EShLangGeometry, "gs", source_code, SHADER_HEADER); + return SPIRV::CompileGeometryShader(GetShaderCode(source_code, SHADER_HEADER), APIType::Vulkan, + GetLanguageVersion()); } std::optional<SPIRVCodeVector> CompileFragmentShader(std::string_view source_code) { - return CompileShaderToSPV(EShLangFragment, "ps", source_code, SHADER_HEADER); + return SPIRV::CompileFragmentShader(GetShaderCode(source_code, SHADER_HEADER), APIType::Vulkan, + GetLanguageVersion()); } std::optional<SPIRVCodeVector> CompileComputeShader(std::string_view source_code) { - return CompileShaderToSPV(EShLangCompute, "cs", source_code, COMPUTE_SHADER_HEADER); + return SPIRV::CompileComputeShader(GetShaderCode(source_code, SHADER_HEADER), APIType::Vulkan, + GetLanguageVersion()); } } // namespace Vulkan::ShaderCompiler |
