diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp index 907952a99..d37591974 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp @@ -43,6 +43,8 @@ struct AnyConverter::State { Containers::Array> definitions; Containers::Array> definitionViews; + + Containers::String debugInfoLevel; }; AnyConverter::AnyConverter(PluginManager::Manager& manager): AbstractConverter{manager} {} @@ -52,9 +54,8 @@ AnyConverter::AnyConverter(PluginManager::AbstractManager& manager, const std::s AnyConverter::~AnyConverter() = default; ConverterFeatures AnyConverter::doFeatures() const { - /** @todo Optimize, DebugInfo, those also need checks that the plugin - actually supports them */ - return ConverterFeature::ValidateFile|ConverterFeature::ConvertFile|ConverterFeature::Preprocess; + /** @todo Optimize, also need checks that the plugin actually supports it */ + return ConverterFeature::ValidateFile|ConverterFeature::ConvertFile|ConverterFeature::Preprocess|ConverterFeature::DebugInfo; } void AnyConverter::doSetInputFormat(const Format format, const Containers::StringView version) { @@ -89,6 +90,10 @@ void AnyConverter::doSetDefinitions(const Containers::ArrayViewdebugInfoLevel = Containers::String::nullTerminatedGlobalView(level); +} + namespace { using namespace Containers::Literals; @@ -238,14 +243,22 @@ bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::Stri return {}; } + /* Check that it can output debug info, in case we were asked to */ + if(!_state->debugInfoLevel.isEmpty() && !(converter->features() & ConverterFeature::DebugInfo)) { + Error{} << "ShaderTools::AnyConverter::convertFileToFile():" << metadata->name() << "does not support controlling debug info output"; + return {}; + } + /* Propagate input/output version and flags */ converter->setFlags(flags()); converter->setInputFormat(_state->inputFormat, _state->inputVersion); converter->setOutputFormat(_state->outputFormat, _state->outputVersion); - /* Propagate definitions, if any */ + /* Propagate definitions and debug info, if any */ if(!_state->definitionViews.empty()) converter->setDefinitions(_state->definitionViews); + if(!_state->debugInfoLevel.isEmpty()) + converter->setDebugInfoLevel(_state->debugInfoLevel); /* Try to convert the file (error output should be printed by the plugin itself) */ diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h index 1bd0797be..f5c07671f 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h @@ -130,9 +130,12 @@ class MAGNUM_ANYSHADERCONVERTER_EXPORT AnyConverter: public AbstractConverter { private: MAGNUM_ANYSHADERCONVERTER_LOCAL ConverterFeatures doFeatures() const override; + MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetInputFormat(Format, Containers::StringView version) override; MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOutputFormat(Format, Containers::StringView version) override; MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDefinitions(Containers::ArrayView> definitions) override; + MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDebugInfoLevel(Containers::StringView level) override; + MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair doValidateFile(Stage stage, Containers::StringView filename) override; MAGNUM_ANYSHADERCONVERTER_LOCAL bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to) override; diff --git a/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp b/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp index 6ee39a535..faadbd3c5 100644 --- a/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp @@ -53,10 +53,12 @@ struct AnyConverterTest: TestSuite::Tester { void convert(); void convertNotSupported(); void convertPreprocessNotSupported(); + void convertDebugInfoNotSupported(); void convertPropagateFlags(); void convertPropagateInputVersion(); void convertPropagateOutputVersion(); void convertPropagatePreprocess(); + void convertPropagateDebugInfo(); void detectValidate(); void detectConvert(); @@ -103,10 +105,12 @@ AnyConverterTest::AnyConverterTest() { &AnyConverterTest::convert, &AnyConverterTest::convertNotSupported, &AnyConverterTest::convertPreprocessNotSupported, + &AnyConverterTest::convertDebugInfoNotSupported, &AnyConverterTest::convertPropagateFlags, &AnyConverterTest::convertPropagateInputVersion, &AnyConverterTest::convertPropagateOutputVersion, - &AnyConverterTest::convertPropagatePreprocess}); + &AnyConverterTest::convertPropagatePreprocess, + &AnyConverterTest::convertPropagateDebugInfo}); addInstancedTests({&AnyConverterTest::detectValidate}, Containers::arraySize(DetectValidateData)); @@ -331,6 +335,29 @@ void AnyConverterTest::convertPreprocessNotSupported() { "ShaderTools::AnyConverter::convertFileToFile(): SpirvToolsShaderConverter does not support preprocessing\n"); } +void AnyConverterTest::convertDebugInfoNotSupported() { + PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; + #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.load("SpirvToolsShaderConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("SpirvToolsShaderConverter plugin can't be loaded."); + + Containers::Pointer converter = manager.instantiate("AnyShaderConverter"); + + converter->setDebugInfoLevel("1"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToFile({}, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv"), + Utility::Directory::join(ANYSHADERCONVERTER_TEST_OUTPUT_DIR, "file.spvasm"))); + /** @todo it one may support that, in which case we need to find another + victim */ + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertFileToFile(): SpirvToolsShaderConverter does not support controlling debug info output\n"); +} + void AnyConverterTest::convertPropagateFlags() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME @@ -443,6 +470,30 @@ void AnyConverterTest::convertPropagatePreprocess() { "WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved\n", inputFilename)); } +void AnyConverterTest::convertPropagateDebugInfo() { + PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; + #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME + CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); + #endif + + if(manager.load("GlslangShaderConverter") < PluginManager::LoadState::Loaded) + CORRADE_SKIP("GlslangShaderConverter plugin can't be loaded."); + + Containers::Pointer converter = manager.instantiate("AnyShaderConverter"); + + /* This is an invalid level */ + converter->setDebugInfoLevel("2"); + + /* We have to supply a valid file path because the version gets checked in + doConvertDataToData(), called from AbstractConverter::doConvertFileToFile() + with the file contents. */ + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToFile(Stage::Fragment, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"), Utility::Directory::join(ANYSHADERCONVERTER_TEST_OUTPUT_DIR, "file.spv"))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): debug info level should be 0, 1 or empty but got 2\n"); +} + void AnyConverterTest::detectValidate() { auto&& data = DetectValidateData[testCaseInstanceId()]; setTestCaseDescription(data.name);