diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp index 226612626..ca7788d6e 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp @@ -54,7 +54,7 @@ AnyConverter::AnyConverter(PluginManager::AbstractManager& manager, const std::s AnyConverter::~AnyConverter() = default; ConverterFeatures AnyConverter::doFeatures() const { - return ConverterFeature::ValidateFile|ConverterFeature::ConvertFile|ConverterFeature::Preprocess|ConverterFeature::DebugInfo|ConverterFeature::Optimize; + return ConverterFeature::ValidateFile|ConverterFeature::ValidateData|ConverterFeature::ConvertFile|ConverterFeature::ConvertData|ConverterFeature::Preprocess|ConverterFeature::DebugInfo|ConverterFeature::Optimize; } void AnyConverter::doSetInputFormat(const Format format, const Containers::StringView version) { @@ -228,6 +228,59 @@ std::pair AnyConverter::doValidateFile(const Stage sta return converter->validateFile(stage, filename); } +std::pair AnyConverter::doValidateData(const Stage stage, const Containers::ArrayView data) { + CORRADE_INTERNAL_ASSERT(manager()); + + /* Decide on a plugin name based on the format */ + if(_state->inputFormat == Format::Unspecified) { + Error{} << "ShaderTools::AnyConverter::validateData(): no input format specified"; + return {}; + } + const std::string plugin = Utility::formatString("{}ShaderConverter", stringForFormat(_state->inputFormat)); + + /* Try to load the plugin */ + if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) { + Error{} << "ShaderTools::AnyConverter::validateData(): cannot load the" << plugin << "plugin"; + return {}; + } + PluginManager::PluginMetadata* metadata = manager()->metadata(plugin); + if(flags() & ConverterFlag::Verbose) { + Debug d; + d << "ShaderTools::AnyConverter::validateData(): using" << plugin; + CORRADE_INTERNAL_ASSERT(metadata); + if(plugin != metadata->name()) + d << "(provided by" << metadata->name() << Debug::nospace << ")"; + } + + /* Instantiate the plugin */ + Containers::Pointer converter = static_cast*>(manager())->instantiate(plugin); + + /* Check that it can actually validate */ + if(!(converter->features() & ConverterFeature::ValidateData)) { + Error{} << "ShaderTools::AnyConverter::validateData():" << metadata->name() << "does not support validation"; + return {}; + } + + /* Check that it can preprocess, in case we were asked to preprocess */ + if((!_state->definitionViews.empty() || (flags() & ConverterFlag::PreprocessOnly)) && !(converter->features() & ConverterFeature::Preprocess)) { + Error{} << "ShaderTools::AnyConverter::validateData():" << metadata->name() << "does not support preprocessing"; + 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 */ + if(!_state->definitionViews.empty()) + converter->setDefinitions(_state->definitionViews); + + /* Try to validate the data (error output should be printed by the plugin + itself) */ + return converter->validateData(stage, data); +} + bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::StringView from, const Containers::StringView to) { CORRADE_INTERNAL_ASSERT(manager()); @@ -308,6 +361,166 @@ bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::Stri return converter->convertFileToFile(stage, from, to); } +Containers::Array AnyConverter::doConvertFileToData(const Stage stage, const Containers::StringView from) { + CORRADE_INTERNAL_ASSERT(manager()); + + /* Prefer the explicitly set input format. If not set, fall back to + detecting based on input and output extension. */ + const Containers::StringView formatFrom = stringForFormat( + _state->inputFormat != Format::Unspecified ? _state->inputFormat : formatForExtension("ShaderTools::AnyConverter::convertFileToData():", from) + ); + if(formatFrom.isEmpty()) return {}; + if(_state->outputFormat == Format::Unspecified) { + Error{} << "ShaderTools::AnyConverter::convertFileToData(): no output format specified"; + return {}; + } + const Containers::StringView formatTo = stringForFormat(_state->outputFormat); + + /* Decide on a plugin name based on the format. This might result in + invalid combinations such as SpirvToGlslShaderConverter which can't be + really handled yet but I think that's okay for now. */ + const std::string plugin = Utility::formatString( + formatFrom == formatTo ? "{}ShaderConverter" : "{}To{}ShaderConverter", + formatFrom, formatTo); + + /* Try to load the plugin */ + if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) { + Error{} << "ShaderTools::AnyConverter::convertFileToData(): cannot load the" << plugin << "plugin"; + return {}; + } + PluginManager::PluginMetadata* metadata = manager()->metadata(plugin); + if(flags() & ConverterFlag::Verbose) { + Debug d; + d << "ShaderTools::AnyConverter::convertFileToData(): using" << plugin; + CORRADE_INTERNAL_ASSERT(metadata); + if(plugin != metadata->name()) + d << "(provided by" << metadata->name() << Debug::nospace << ")"; + } + + /* Instantiate the plugin */ + Containers::Pointer converter = static_cast*>(manager())->instantiate(plugin); + + /* Check that it can actually convert */ + if(!(converter->features() & ConverterFeature::ConvertData)) { + Error{} << "ShaderTools::AnyConverter::convertFileToData():" << metadata->name() << "does not support conversion"; + return {}; + } + + /* Check that it can preprocess, in case we were asked to preprocess */ + if((!_state->definitionViews.empty() || (flags() & ConverterFlag::PreprocessOnly)) && !(converter->features() & ConverterFeature::Preprocess)) { + Error{} << "ShaderTools::AnyConverter::convertFileToData():" << metadata->name() << "does not support preprocessing"; + 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::convertFileToData():" << metadata->name() << "does not support controlling debug info output"; + return {}; + } + + /* Check that it can optimize, in case we were asked to */ + if(!_state->optimizationLevel.isEmpty() && !(converter->features() & ConverterFeature::Optimize)) { + Error{} << "ShaderTools::AnyConverter::convertFileToData():" << metadata->name() << "does not support optimization"; + return {}; + } + + /* Propagate input/output version and flags */ + converter->setFlags(flags()); + converter->setInputFormat(_state->inputFormat, _state->inputVersion); + converter->setOutputFormat(_state->outputFormat, _state->outputVersion); + + /* Propagate definitions and debug info, if any */ + if(!_state->definitionViews.empty()) + converter->setDefinitions(_state->definitionViews); + if(!_state->debugInfoLevel.isEmpty()) + converter->setDebugInfoLevel(_state->debugInfoLevel); + if(!_state->optimizationLevel.isEmpty()) + converter->setOptimizationLevel(_state->optimizationLevel); + + /* Try to convert the file (error output should be printed by the plugin + itself) */ + return converter->convertFileToData(stage, from); +} + +Containers::Array AnyConverter::doConvertDataToData(const Stage stage, const Containers::ArrayView from) { + CORRADE_INTERNAL_ASSERT(manager()); + + /* Decide on a plugin name based on the format. This might result in + invalid combinations such as SpirvToGlslShaderConverter which can't be + really handled yet but I think that's okay for now. */ + if(_state->inputFormat == Format::Unspecified) { + Error{} << "ShaderTools::AnyConverter::convertDataToData(): no input format specified"; + return {}; + } + if(_state->outputFormat == Format::Unspecified) { + Error{} << "ShaderTools::AnyConverter::convertDataToData(): no output format specified"; + return {}; + } + const Containers::StringView formatFrom = stringForFormat(_state->inputFormat); + const Containers::StringView formatTo = stringForFormat(_state->outputFormat); + const std::string plugin = Utility::formatString( + formatFrom == formatTo ? "{}ShaderConverter" : "{}To{}ShaderConverter", + formatFrom, formatTo); + + /* Try to load the plugin */ + if(!(manager()->load(plugin) & PluginManager::LoadState::Loaded)) { + Error{} << "ShaderTools::AnyConverter::convertDataToData(): cannot load the" << plugin << "plugin"; + return {}; + } + PluginManager::PluginMetadata* metadata = manager()->metadata(plugin); + if(flags() & ConverterFlag::Verbose) { + Debug d; + d << "ShaderTools::AnyConverter::convertDataToData(): using" << plugin; + CORRADE_INTERNAL_ASSERT(metadata); + if(plugin != metadata->name()) + d << "(provided by" << metadata->name() << Debug::nospace << ")"; + } + + /* Instantiate the plugin */ + Containers::Pointer converter = static_cast*>(manager())->instantiate(plugin); + + /* Check that it can actually convert */ + if(!(converter->features() & ConverterFeature::ConvertData)) { + Error{} << "ShaderTools::AnyConverter::convertDataToData():" << metadata->name() << "does not support conversion"; + return {}; + } + + /* Check that it can preprocess, in case we were asked to preprocess */ + if((!_state->definitionViews.empty() || (flags() & ConverterFlag::PreprocessOnly)) && !(converter->features() & ConverterFeature::Preprocess)) { + Error{} << "ShaderTools::AnyConverter::convertDataToData():" << metadata->name() << "does not support preprocessing"; + 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::convertDataToData():" << metadata->name() << "does not support controlling debug info output"; + return {}; + } + + /* Check that it can optimize, in case we were asked to */ + if(!_state->optimizationLevel.isEmpty() && !(converter->features() & ConverterFeature::Optimize)) { + Error{} << "ShaderTools::AnyConverter::convertDataToData():" << metadata->name() << "does not support optimization"; + return {}; + } + + /* Propagate input/output version and flags */ + converter->setFlags(flags()); + converter->setInputFormat(_state->inputFormat, _state->inputVersion); + converter->setOutputFormat(_state->outputFormat, _state->outputVersion); + + /* Propagate definitions and debug info, if any */ + if(!_state->definitionViews.empty()) + converter->setDefinitions(_state->definitionViews); + if(!_state->debugInfoLevel.isEmpty()) + converter->setDebugInfoLevel(_state->debugInfoLevel); + if(!_state->optimizationLevel.isEmpty()) + converter->setOptimizationLevel(_state->optimizationLevel); + + /* Try to convert the file (error output should be printed by the plugin + itself) */ + return converter->convertDataToData(stage, from); +} + }} CORRADE_PLUGIN_REGISTER(AnyShaderConverter, Magnum::ShaderTools::AnyConverter, diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h index 950e54b92..859f20445 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h @@ -88,7 +88,9 @@ Supported conversion paths: - SPIR-V Assembly to SPIR-V Assembly, converted with any plugin that provides `SpirvAssemblyShaderConverter` -Only validating and converting files is supported. +There's format detection based on file contents, so the plugin has to either +operate on files or @ref setInputFormat() / @ref setOutputFormat() has to be +explicitly set. @section ShaderTools-AnyConverter-usage Usage @@ -140,7 +142,10 @@ class MAGNUM_ANYSHADERCONVERTER_EXPORT AnyConverter: public AbstractConverter { MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOptimizationLevel(Containers::StringView level) override; MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair doValidateFile(Stage stage, Containers::StringView filename) override; + MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair doValidateData(Stage stage, Containers::ArrayView data) override; MAGNUM_ANYSHADERCONVERTER_LOCAL bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to) override; + MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Array doConvertFileToData(Magnum::ShaderTools::Stage stage, Containers::StringView from) override; + MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Array doConvertDataToData(Magnum::ShaderTools::Stage stage, Containers::ArrayView data) override; struct State; Containers::Pointer _state; diff --git a/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp b/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp index e90f2ed3b..498ea94cc 100644 --- a/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp @@ -24,7 +24,7 @@ */ #include -#include +#include #include #include #include @@ -43,28 +43,70 @@ namespace Magnum { namespace ShaderTools { namespace Test { namespace { struct AnyConverterTest: TestSuite::Tester { explicit AnyConverterTest(); - void validate(); - void validateUnknown(); - void validateNotSupported(); - void validatePreprocessNotSupported(); - void validatePropagateFlags(); - void validatePropagateInputVersion(); - void validatePropagateOutputVersion(); - void validatePropagatePreprocess(); - - void convert(); - void convertUnknownInput(); - void convertUnknownOutput(); - void convertNotSupported(); - void convertPreprocessNotSupported(); - void convertDebugInfoNotSupported(); - void convertOptimizationNotSupported(); - void convertPropagateFlags(); - void convertPropagateInputVersion(); - void convertPropagateOutputVersion(); - void convertPropagatePreprocess(); - void convertPropagateDebugInfo(); - void convertPropagateOptimization(); + void validateFile(); + void validateFilePluginLoadFailed(); + void validateFileUnknown(); + void validateFileNotSupported(); + void validateFilePreprocessNotSupported(); + void validateFilePropagateFlags(); + void validateFilePropagateInputVersion(); + void validateFilePropagateOutputVersion(); + void validateFilePropagatePreprocess(); + + void validateData(); + void validateDataPluginLoadFailed(); + void validateDataNoFormatSet(); + void validateDataNotSupported(); + void validateDataPreprocessNotSupported(); + void validateDataPropagateFlags(); + void validateDataPropagateInputVersion(); + void validateDataPropagateOutputVersion(); + void validateDataPropagatePreprocess(); + + void convertFileToFile(); + void convertFileToFilePluginLoadFailed(); + void convertFileToFileUnknownInput(); + void convertFileToFileUnknownOutput(); + void convertFileToFileNotSupported(); + void convertFileToFilePreprocessNotSupported(); + void convertFileToFileDebugInfoNotSupported(); + void convertFileToFileOptimizationNotSupported(); + void convertFileToFilePropagateFlags(); + void convertFileToFilePropagateInputVersion(); + void convertFileToFilePropagateOutputVersion(); + void convertFileToFilePropagatePreprocess(); + void convertFileToFilePropagateDebugInfo(); + void convertFileToFilePropagateOptimization(); + + void convertFileToData(); + void convertFileToDataPluginLoadFailed(); + void convertFileToDataUnknown(); + void convertFileToDataNoFormatSet(); + void convertFileToDataNotSupported(); + void convertFileToDataPreprocessNotSupported(); + void convertFileToDataDebugInfoNotSupported(); + void convertFileToDataOptimizationNotSupported(); + void convertFileToDataPropagateFlags(); + void convertFileToDataPropagateInputVersion(); + void convertFileToDataPropagateOutputVersion(); + void convertFileToDataPropagatePreprocess(); + void convertFileToDataPropagateDebugInfo(); + void convertFileToDataPropagateOptimization(); + + void convertDataToData(); + void convertDataToDataPluginLoadFailed(); + void convertDataToDataNoInputFormatSet(); + void convertDataToDataNoOutputFormatSet(); + void convertDataToDataNotSupported(); + void convertDataToDataPreprocessNotSupported(); + void convertDataToDataDebugInfoNotSupported(); + void convertDataToDataOptimizationNotSupported(); + void convertDataToDataPropagateFlags(); + void convertDataToDataPropagateInputVersion(); + void convertDataToDataPropagateOutputVersion(); + void convertDataToDataPropagatePreprocess(); + void convertDataToDataPropagateDebugInfo(); + void convertDataToDataPropagateOptimization(); void detectValidate(); void detectValidateExplicitFormat(); @@ -100,28 +142,70 @@ constexpr struct { }; AnyConverterTest::AnyConverterTest() { - addTests({&AnyConverterTest::validate, - &AnyConverterTest::validateUnknown, - &AnyConverterTest::validateNotSupported, - &AnyConverterTest::validatePreprocessNotSupported, - &AnyConverterTest::validatePropagateFlags, - &AnyConverterTest::validatePropagateInputVersion, - &AnyConverterTest::validatePropagateOutputVersion, - &AnyConverterTest::validatePropagatePreprocess, - - &AnyConverterTest::convert, - &AnyConverterTest::convertUnknownInput, - &AnyConverterTest::convertUnknownOutput, - &AnyConverterTest::convertNotSupported, - &AnyConverterTest::convertPreprocessNotSupported, - &AnyConverterTest::convertDebugInfoNotSupported, - &AnyConverterTest::convertOptimizationNotSupported, - &AnyConverterTest::convertPropagateFlags, - &AnyConverterTest::convertPropagateInputVersion, - &AnyConverterTest::convertPropagateOutputVersion, - &AnyConverterTest::convertPropagatePreprocess, - &AnyConverterTest::convertPropagateDebugInfo, - &AnyConverterTest::convertPropagateOptimization}); + addTests({&AnyConverterTest::validateFile, + &AnyConverterTest::validateFilePluginLoadFailed, + &AnyConverterTest::validateFileUnknown, + &AnyConverterTest::validateFileNotSupported, + &AnyConverterTest::validateFilePreprocessNotSupported, + &AnyConverterTest::validateFilePropagateFlags, + &AnyConverterTest::validateFilePropagateInputVersion, + &AnyConverterTest::validateFilePropagateOutputVersion, + &AnyConverterTest::validateFilePropagatePreprocess, + + &AnyConverterTest::validateData, + &AnyConverterTest::validateDataPluginLoadFailed, + &AnyConverterTest::validateDataNoFormatSet, + &AnyConverterTest::validateDataNotSupported, + &AnyConverterTest::validateDataPreprocessNotSupported, + &AnyConverterTest::validateDataPropagateFlags, + &AnyConverterTest::validateDataPropagateInputVersion, + &AnyConverterTest::validateDataPropagateOutputVersion, + &AnyConverterTest::validateDataPropagatePreprocess, + + &AnyConverterTest::convertFileToFile, + &AnyConverterTest::convertFileToFilePluginLoadFailed, + &AnyConverterTest::convertFileToFileUnknownInput, + &AnyConverterTest::convertFileToFileUnknownOutput, + &AnyConverterTest::convertFileToFileNotSupported, + &AnyConverterTest::convertFileToFilePreprocessNotSupported, + &AnyConverterTest::convertFileToFileDebugInfoNotSupported, + &AnyConverterTest::convertFileToFileOptimizationNotSupported, + &AnyConverterTest::convertFileToFilePropagateFlags, + &AnyConverterTest::convertFileToFilePropagateInputVersion, + &AnyConverterTest::convertFileToFilePropagateOutputVersion, + &AnyConverterTest::convertFileToFilePropagatePreprocess, + &AnyConverterTest::convertFileToFilePropagateDebugInfo, + &AnyConverterTest::convertFileToFilePropagateOptimization, + + &AnyConverterTest::convertFileToData, + &AnyConverterTest::convertFileToDataPluginLoadFailed, + &AnyConverterTest::convertFileToDataUnknown, + &AnyConverterTest::convertFileToDataNoFormatSet, + &AnyConverterTest::convertFileToDataNotSupported, + &AnyConverterTest::convertFileToDataPreprocessNotSupported, + &AnyConverterTest::convertFileToDataDebugInfoNotSupported, + &AnyConverterTest::convertFileToDataOptimizationNotSupported, + &AnyConverterTest::convertFileToDataPropagateFlags, + &AnyConverterTest::convertFileToDataPropagateInputVersion, + &AnyConverterTest::convertFileToDataPropagateOutputVersion, + &AnyConverterTest::convertFileToDataPropagatePreprocess, + &AnyConverterTest::convertFileToDataPropagateDebugInfo, + &AnyConverterTest::convertFileToDataPropagateOptimization, + + &AnyConverterTest::convertDataToData, + &AnyConverterTest::convertDataToDataPluginLoadFailed, + &AnyConverterTest::convertDataToDataNoInputFormatSet, + &AnyConverterTest::convertDataToDataNoOutputFormatSet, + &AnyConverterTest::convertDataToDataNotSupported, + &AnyConverterTest::convertDataToDataPreprocessNotSupported, + &AnyConverterTest::convertDataToDataDebugInfoNotSupported, + &AnyConverterTest::convertDataToDataOptimizationNotSupported, + &AnyConverterTest::convertDataToDataPropagateFlags, + &AnyConverterTest::convertDataToDataPropagateInputVersion, + &AnyConverterTest::convertDataToDataPropagateOutputVersion, + &AnyConverterTest::convertDataToDataPropagatePreprocess, + &AnyConverterTest::convertDataToDataPropagateDebugInfo, + &AnyConverterTest::convertDataToDataPropagateOptimization}); addInstancedTests({&AnyConverterTest::detectValidate}, Containers::arraySize(DetectValidateData)); @@ -143,7 +227,7 @@ AnyConverterTest::AnyConverterTest() { CORRADE_INTERNAL_ASSERT_OUTPUT(Utility::Directory::mkpath(ANYSHADERCONVERTER_TEST_OUTPUT_DIR)); } -void AnyConverterTest::validate() { +void AnyConverterTest::validateFile() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -161,7 +245,25 @@ void AnyConverterTest::validate() { std::make_pair(true, Utility::formatString("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename))); } -void AnyConverterTest::validateUnknown() { +void AnyConverterTest::validateFilePluginLoadFailed() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_COMPARE(converter->validateFile({}, "file.glsl"), + std::make_pair(false, "")); + #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n" + "ShaderTools::AnyConverter::validateFile(): cannot load the GlslShaderConverter plugin\n"); + #else + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin GlslShaderConverter was not found\n" + "ShaderTools::AnyConverter::validateFile(): cannot load the GlslShaderConverter plugin\n"); + #endif +} + +void AnyConverterTest::validateFileUnknown() { Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); std::ostringstream out; @@ -171,11 +273,11 @@ void AnyConverterTest::validateUnknown() { CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateFile(): cannot determine the format of dead.cg\n"); } -void AnyConverterTest::validateNotSupported() { +void AnyConverterTest::validateFileNotSupported() { CORRADE_SKIP("No plugin that would support just validation exists."); } -void AnyConverterTest::validatePreprocessNotSupported() { +void AnyConverterTest::validateFilePreprocessNotSupported() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -198,7 +300,7 @@ void AnyConverterTest::validatePreprocessNotSupported() { "ShaderTools::AnyConverter::validateFile(): SpirvToolsShaderConverter does not support preprocessing\n"); } -void AnyConverterTest::validatePropagateFlags() { +void AnyConverterTest::validateFilePropagateFlags() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -223,7 +325,7 @@ void AnyConverterTest::validatePropagateFlags() { "ShaderTools::AnyConverter::validateFile(): using GlslShaderConverter (provided by GlslangShaderConverter)\n"); } -void AnyConverterTest::validatePropagateInputVersion() { +void AnyConverterTest::validateFilePropagateInputVersion() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -247,7 +349,7 @@ void AnyConverterTest::validatePropagateInputVersion() { "ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n"); } -void AnyConverterTest::validatePropagateOutputVersion() { +void AnyConverterTest::validateFilePropagateOutputVersion() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -271,7 +373,7 @@ void AnyConverterTest::validatePropagateOutputVersion() { "ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n"); } -void AnyConverterTest::validatePropagatePreprocess() { +void AnyConverterTest::validateFilePropagatePreprocess() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -296,7 +398,186 @@ void AnyConverterTest::validatePropagatePreprocess() { std::make_pair(true, Utility::formatString("WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved", filename))); } -void AnyConverterTest::convert() { +void AnyConverterTest::validateData() { + 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"); + + converter->setInputFormat(Format::Glsl); + + /* Make it print a warning so we know it's doing something */ + CORRADE_COMPARE(converter->validateData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))), + std::make_pair(true, "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved")); +} + +void AnyConverterTest::validateDataPluginLoadFailed() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + converter->setInputFormat(Format::Glsl); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_COMPARE(converter->validateData({}, {}), + std::make_pair(false, "")); + #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n" + "ShaderTools::AnyConverter::validateData(): cannot load the GlslShaderConverter plugin\n"); + #else + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin GlslShaderConverter was not found\n" + "ShaderTools::AnyConverter::validateData(): cannot load the GlslShaderConverter plugin\n"); + #endif +} + +void AnyConverterTest::validateDataNoFormatSet() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_COMPARE(converter->validateData({}, "dead.cg"), + std::make_pair(false, "")); + CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateData(): no input format specified\n"); +} + +void AnyConverterTest::validateDataNotSupported() { + CORRADE_SKIP("No plugin that would support just validation exists."); +} + +void AnyConverterTest::validateDataPreprocessNotSupported() { + 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->setInputFormat(Format::Spirv); + + converter->setDefinitions({ + {"DEFINE", "hahahahah"} + }); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_COMPARE(converter->validateData({}, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv"))), + std::make_pair(false, "")); + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::validateData(): SpirvToolsShaderConverter does not support preprocessing\n"); +} + +void AnyConverterTest::validateDataPropagateFlags() { + 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"); + + converter->setInputFormat(Format::Glsl); + + /* With this, the warning should turn into an error. The converter should + also print the verbose info. */ + converter->setFlags(ConverterFlag::Verbose|ConverterFlag::WarningAsError); + + std::ostringstream out; + Debug redirectDebug{&out}; + CORRADE_COMPARE(converter->validateData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))), + std::make_pair(false, "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved")); + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::validateData(): using GlslShaderConverter (provided by GlslangShaderConverter)\n"); +} + +void AnyConverterTest::validateDataPropagateInputVersion() { + 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"); + + converter->setInputFormat(Format::Glsl); + + /* This is an invalid version. We have to supply a valid file path because + the version gets checked in doValidateData(), called from + AbstractConverter::doValidateFile() with the file contents. */ + converter->setInputFormat(Format::Glsl, "100"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_COMPARE(converter->validateData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))), + std::make_pair(false, "")); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n"); +} + +void AnyConverterTest::validateDataPropagateOutputVersion() { + 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"); + + converter->setInputFormat(Format::Glsl); + + /* This is an invalid version. We have to supply a valid file path because + the version gets checked in doValidateData(), called from + AbstractConverter::doValidateFile() with the file contents. */ + converter->setOutputFormat(Format::Glsl, "opengl4.0"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_COMPARE(converter->validateData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))), + std::make_pair(false, "")); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n"); +} + +void AnyConverterTest::validateDataPropagatePreprocess() { + 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"); + + converter->setInputFormat(Format::Glsl); + + /* Check that undefining works properly -- if it stays defined, the source + won't compile */ + converter->setDefinitions({ + {"SHOULD_BE_UNDEFINED", "really"}, + {"SHOULD_BE_UNDEFINED", nullptr}, + {"reserved__identifier", "different__but_also_wrong"} + }); + + CORRADE_COMPARE(converter->validateData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))), + std::make_pair(true, "WARNING: 0:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved")); +} + +void AnyConverterTest::convertFileToFile() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -322,7 +603,24 @@ void AnyConverterTest::convert() { "WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved\n", inputFilename)); } -void AnyConverterTest::convertUnknownInput() { +void AnyConverterTest::convertFileToFilePluginLoadFailed() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToFile({}, "file.spv", "file.glsl")); + #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin SpirvToGlslShaderConverter is not static and was not found in nonexistent\n" + "ShaderTools::AnyConverter::convertFileToFile(): cannot load the SpirvToGlslShaderConverter plugin\n"); + #else + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin SpirvToGlslShaderConverter was not found\n" + "ShaderTools::AnyConverter::convertFileToFile(): cannot load the SpirvToGlslShaderConverter plugin\n"); + #endif +} + +void AnyConverterTest::convertFileToFileUnknownInput() { Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); std::ostringstream out; @@ -331,7 +629,7 @@ void AnyConverterTest::convertUnknownInput() { CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::convertFileToFile(): cannot determine the format of dead.cg\n"); } -void AnyConverterTest::convertUnknownOutput() { +void AnyConverterTest::convertFileToFileUnknownOutput() { Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); std::ostringstream out; @@ -340,11 +638,11 @@ void AnyConverterTest::convertUnknownOutput() { CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::convertFileToFile(): cannot determine the format of whatever.osl\n"); } -void AnyConverterTest::convertNotSupported() { +void AnyConverterTest::convertFileToFileNotSupported() { CORRADE_SKIP("No plugin that would support just conversion exists."); } -void AnyConverterTest::convertPreprocessNotSupported() { +void AnyConverterTest::convertFileToFilePreprocessNotSupported() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -376,7 +674,7 @@ void AnyConverterTest::convertPreprocessNotSupported() { "ShaderTools::AnyConverter::convertFileToFile(): SpirvToolsShaderConverter does not support preprocessing\n"); } -void AnyConverterTest::convertDebugInfoNotSupported() { +void AnyConverterTest::convertFileToFileDebugInfoNotSupported() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -399,7 +697,7 @@ void AnyConverterTest::convertDebugInfoNotSupported() { "ShaderTools::AnyConverter::convertFileToFile(): SpirvToolsShaderConverter does not support controlling debug info output\n"); } -void AnyConverterTest::convertOptimizationNotSupported() { +void AnyConverterTest::convertFileToFileOptimizationNotSupported() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -422,7 +720,7 @@ void AnyConverterTest::convertOptimizationNotSupported() { "ShaderTools::AnyConverter::convertFileToFile(): GlslangShaderConverter does not support optimization\n"); } -void AnyConverterTest::convertPropagateFlags() { +void AnyConverterTest::convertFileToFilePropagateFlags() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -452,7 +750,7 @@ void AnyConverterTest::convertPropagateFlags() { "WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved\n", filename)); } -void AnyConverterTest::convertPropagateInputVersion() { +void AnyConverterTest::convertFileToFilePropagateInputVersion() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -476,7 +774,7 @@ void AnyConverterTest::convertPropagateInputVersion() { "ShaderTools::GlslangConverter::convertDataToData(): input format version should be one of supported GLSL #version strings but got 100\n"); } -void AnyConverterTest::convertPropagateOutputVersion() { +void AnyConverterTest::convertFileToFilePropagateOutputVersion() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -500,7 +798,7 @@ void AnyConverterTest::convertPropagateOutputVersion() { "ShaderTools::GlslangConverter::convertDataToData(): output format version target should be opengl4.5 or vulkanX.Y but got opengl4.0\n"); } -void AnyConverterTest::convertPropagatePreprocess() { +void AnyConverterTest::convertFileToFilePropagatePreprocess() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -534,7 +832,7 @@ void AnyConverterTest::convertPropagatePreprocess() { "WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved\n", inputFilename)); } -void AnyConverterTest::convertPropagateDebugInfo() { +void AnyConverterTest::convertFileToFilePropagateDebugInfo() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -558,7 +856,7 @@ void AnyConverterTest::convertPropagateDebugInfo() { "ShaderTools::GlslangConverter::convertDataToData(): debug info level should be 0, 1 or empty but got 2\n"); } -void AnyConverterTest::convertPropagateOptimization() { +void AnyConverterTest::convertFileToFilePropagateOptimization() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME CORRADE_VERIFY(manager.load(ANYSHADERCONVERTER_PLUGIN_FILENAME) & PluginManager::LoadState::Loaded); @@ -582,6 +880,635 @@ void AnyConverterTest::convertPropagateOptimization() { "ShaderTools::SpirvToolsConverter::convertDataToData(): optimization level should be 0, 1, s, legalizeHlsl, vulkanToWebGpu, webGpuToVulkan or empty but got 2\n"); } +void AnyConverterTest::convertFileToData() { + 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"); + + converter->setOutputFormat(Format::Spirv); + + const std::string inputFilename = Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"); + + /* Make it print a warning so we know it's doing something */ + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertFileToData(Stage::Fragment, inputFilename)); + CORRADE_COMPARE(out.str(), Utility::formatString( + "ShaderTools::GlslangConverter::convertDataToData(): compilation succeeded with the following message:\n" + "WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved\n", inputFilename)); +} + +void AnyConverterTest::convertFileToDataPluginLoadFailed() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + converter->setOutputFormat(Format::Wgsl); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToData({}, "file.spv")); + #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin SpirvToWgslShaderConverter is not static and was not found in nonexistent\n" + "ShaderTools::AnyConverter::convertFileToData(): cannot load the SpirvToWgslShaderConverter plugin\n"); + #else + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin SpirvToWgslShaderConverter was not found\n" + "ShaderTools::AnyConverter::convertFileToData(): cannot load the SpirvToWgslShaderConverter plugin\n"); + #endif +} + +void AnyConverterTest::convertFileToDataUnknown() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToData({}, "dead.cg")); + CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::convertFileToData(): cannot determine the format of dead.cg\n"); +} + +void AnyConverterTest::convertFileToDataNoFormatSet() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToData({}, "file.spv")); + CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::convertFileToData(): no output format specified\n"); +} + +void AnyConverterTest::convertFileToDataNotSupported() { + CORRADE_SKIP("No plugin that would support just conversion exists."); +} + +void AnyConverterTest::convertFileToDataPreprocessNotSupported() { + 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->setOutputFormat(Format::SpirvAssembly); + + converter->setDefinitions({ + {"DEFINE", "hahahahah"} + }); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToData({}, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv"))); + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertFileToData(): SpirvToolsShaderConverter does not support preprocessing\n"); + + /* It should fail for the flag as well */ + out.str({}); + converter->setDefinitions({}); + converter->setFlags(ConverterFlag::PreprocessOnly); + CORRADE_VERIFY(!converter->convertFileToData({}, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv"))); + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertFileToData(): SpirvToolsShaderConverter does not support preprocessing\n"); +} + +void AnyConverterTest::convertFileToDataDebugInfoNotSupported() { + 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->setOutputFormat(Format::SpirvAssembly); + + converter->setDebugInfoLevel("1"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToData({}, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv"))); + /** @todo it once may support that, in which case we need to find another + victim */ + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertFileToData(): SpirvToolsShaderConverter does not support controlling debug info output\n"); +} + +void AnyConverterTest::convertFileToDataOptimizationNotSupported() { + 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"); + + converter->setOutputFormat(Format::Spirv); + + converter->setOptimizationLevel("1"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToData({}, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))); + /** @todo it once may support that, in which case we need to find another + victim */ + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertFileToData(): GlslangShaderConverter does not support optimization\n"); +} + +void AnyConverterTest::convertFileToDataPropagateFlags() { + 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"); + + const std::string filename = Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"); + + converter->setOutputFormat(Format::Spirv); + + /* With this, the warning should turn into an error. The converter should + also print the verbose info. */ + converter->setFlags(ConverterFlag::Verbose|ConverterFlag::WarningAsError); + + /* 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; + Debug redirectDebug{&out}; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToData(Stage::Fragment, filename)); + CORRADE_COMPARE(out.str(), Utility::formatString( + "ShaderTools::AnyConverter::convertFileToData(): using GlslToSpirvShaderConverter (provided by GlslangShaderConverter)\n" + "ShaderTools::GlslangConverter::convertDataToData(): compilation failed:\n" + "WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved\n", filename)); +} + +void AnyConverterTest::convertFileToDataPropagateInputVersion() { + 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 version */ + converter->setInputFormat(Format::Glsl, "100"); + + converter->setOutputFormat(Format::Spirv); + + /* 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->convertFileToData(Stage::Fragment, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): input format version should be one of supported GLSL #version strings but got 100\n"); +} + +void AnyConverterTest::convertFileToDataPropagateOutputVersion() { + 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 version */ + converter->setOutputFormat(Format::Spirv, "opengl4.0"); + + /* 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->convertFileToData(Stage::Fragment, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): output format version target should be opengl4.5 or vulkanX.Y but got opengl4.0\n"); +} + +void AnyConverterTest::convertFileToDataPropagatePreprocess() { + 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"); + + converter->setOutputFormat(Format::Spirv); + + /* Check that undefining works properly -- if it stays defined, the source + won't compile */ + converter->setDefinitions({ + {"SHOULD_BE_UNDEFINED", "really"}, + {"SHOULD_BE_UNDEFINED", nullptr}, + {"reserved__identifier", "different__but_also_wrong"} + }); + + const std::string inputFilename = Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"); + + /* Make it print a warning so we know it's doing something */ + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertFileToData(Stage::Fragment, inputFilename)); + CORRADE_COMPARE(out.str(), Utility::formatString( + "ShaderTools::GlslangConverter::convertDataToData(): compilation succeeded with the following message:\n" + "WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved\n", inputFilename)); +} + +void AnyConverterTest::convertFileToDataPropagateDebugInfo() { + 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"); + + converter->setOutputFormat(Format::Spirv); + + /* 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->convertFileToData(Stage::Fragment, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): debug info level should be 0, 1 or empty but got 2\n"); +} + +void AnyConverterTest::convertFileToDataPropagateOptimization() { + 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->setOutputFormat(Format::Spirv); + + /* This is an invalid level */ + converter->setOptimizationLevel("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->convertFileToData(Stage::Fragment, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv"))); + CORRADE_COMPARE(out.str(), + "ShaderTools::SpirvToolsConverter::convertDataToData(): optimization level should be 0, 1, s, legalizeHlsl, vulkanToWebGpu, webGpuToVulkan or empty but got 2\n"); +} + +void AnyConverterTest::convertDataToData() { + 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"); + + converter->setInputFormat(Format::Glsl); + converter->setOutputFormat(Format::Spirv); + + /* Make it print a warning so we know it's doing something */ + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertDataToData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): compilation succeeded with the following message:\n" + "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved\n"); +} + +void AnyConverterTest::convertDataToDataPluginLoadFailed() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + converter->setInputFormat(Format::Hlsl); + converter->setOutputFormat(Format::Wgsl); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertDataToData({}, {})); + #ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin HlslToWgslShaderConverter is not static and was not found in nonexistent\n" + "ShaderTools::AnyConverter::convertDataToData(): cannot load the HlslToWgslShaderConverter plugin\n"); + #else + CORRADE_COMPARE(out.str(), + "PluginManager::Manager::load(): plugin HlslToWgslShaderConverter was not found\n" + "ShaderTools::AnyConverter::convertDataToData(): cannot load the HlslToWgslShaderConverter plugin\n"); + #endif +} + +void AnyConverterTest::convertDataToDataNoInputFormatSet() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertDataToData({}, {})); + CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::convertDataToData(): no input format specified\n"); +} + +void AnyConverterTest::convertDataToDataNoOutputFormatSet() { + Containers::Pointer converter = _manager.instantiate("AnyShaderConverter"); + + converter->setInputFormat(Format::Spirv); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertDataToData({}, {})); + CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::convertDataToData(): no output format specified\n"); +} + +void AnyConverterTest::convertDataToDataNotSupported() { + CORRADE_SKIP("No plugin that would support just conversion exists."); +} + +void AnyConverterTest::convertDataToDataPreprocessNotSupported() { + 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->setInputFormat(Format::Spirv); + converter->setOutputFormat(Format::SpirvAssembly); + + converter->setDefinitions({ + {"DEFINE", "hahahahah"} + }); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertDataToData({}, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertDataToData(): SpirvToolsShaderConverter does not support preprocessing\n"); + + /* It should fail for the flag as well */ + out.str({}); + converter->setDefinitions({}); + converter->setFlags(ConverterFlag::PreprocessOnly); + CORRADE_VERIFY(!converter->convertDataToData({}, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertDataToData(): SpirvToolsShaderConverter does not support preprocessing\n"); +} + +void AnyConverterTest::convertDataToDataDebugInfoNotSupported() { + 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->setInputFormat(Format::Spirv); + converter->setOutputFormat(Format::SpirvAssembly); + + converter->setDebugInfoLevel("1"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertDataToData({}, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv")))); + /** @todo it once may support that, in which case we need to find another + victim */ + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertDataToData(): SpirvToolsShaderConverter does not support controlling debug info output\n"); +} + +void AnyConverterTest::convertDataToDataOptimizationNotSupported() { + 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"); + + converter->setInputFormat(Format::Glsl); + converter->setOutputFormat(Format::Spirv); + + converter->setOptimizationLevel("1"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertDataToData({}, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")))); + /** @todo it once may support that, in which case we need to find another + victim */ + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertDataToData(): GlslangShaderConverter does not support optimization\n"); +} + +void AnyConverterTest::convertDataToDataPropagateFlags() { + 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"); + + converter->setInputFormat(Format::Glsl); + converter->setOutputFormat(Format::Spirv); + + /* With this, the warning should turn into an error. The converter should + also print the verbose info. */ + converter->setFlags(ConverterFlag::Verbose|ConverterFlag::WarningAsError); + + /* 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; + Debug redirectDebug{&out}; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertDataToData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertDataToData(): using GlslToSpirvShaderConverter (provided by GlslangShaderConverter)\n" + "ShaderTools::GlslangConverter::convertDataToData(): compilation failed:\n" + "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved\n"); +} + +void AnyConverterTest::convertDataToDataPropagateInputVersion() { + 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 version */ + converter->setInputFormat(Format::Glsl, "100"); + + converter->setOutputFormat(Format::Spirv); + + /* 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->convertDataToData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): input format version should be one of supported GLSL #version strings but got 100\n"); +} + +void AnyConverterTest::convertDataToDataPropagateOutputVersion() { + 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"); + + converter->setInputFormat(Format::Glsl); + + /* This is an invalid version */ + converter->setOutputFormat(Format::Spirv, "opengl4.0"); + + /* 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->convertDataToData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): output format version target should be opengl4.5 or vulkanX.Y but got opengl4.0\n"); +} + +void AnyConverterTest::convertDataToDataPropagatePreprocess() { + 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"); + + converter->setInputFormat(Format::Glsl); + converter->setOutputFormat(Format::Spirv); + + /* Check that undefining works properly -- if it stays defined, the source + won't compile */ + converter->setDefinitions({ + {"SHOULD_BE_UNDEFINED", "really"}, + {"SHOULD_BE_UNDEFINED", nullptr}, + {"reserved__identifier", "different__but_also_wrong"} + }); + + /* Make it print a warning so we know it's doing something */ + std::ostringstream out; + Warning redirectWarning{&out}; + CORRADE_VERIFY(converter->convertDataToData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): compilation succeeded with the following message:\n" + "WARNING: 0:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved\n"); +} + +void AnyConverterTest::convertDataToDataPropagateDebugInfo() { + 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"); + + converter->setInputFormat(Format::Glsl); + converter->setOutputFormat(Format::Spirv); + + /* 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->convertDataToData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::GlslangConverter::convertDataToData(): debug info level should be 0, 1 or empty but got 2\n"); +} + +void AnyConverterTest::convertDataToDataPropagateOptimization() { + 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->setInputFormat(Format::Spirv); + converter->setOutputFormat(Format::Spirv); + + /* This is an invalid level */ + converter->setOptimizationLevel("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->convertDataToData(Stage::Fragment, Utility::Directory::read(Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv")))); + CORRADE_COMPARE(out.str(), + "ShaderTools::SpirvToolsConverter::convertDataToData(): optimization level should be 0, 1, s, legalizeHlsl, vulkanToWebGpu, webGpuToVulkan or empty but got 2\n"); +} + void AnyConverterTest::detectValidate() { auto&& data = DetectValidateData[testCaseInstanceId()]; setTestCaseDescription(data.name);