From 38a2a1f6c44771de60baab3283baf9717e04fb35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Thu, 5 Nov 2020 16:50:37 +0100 Subject: [PATCH] AnyShaderConverter: propagate optimization level as well. Finally a complete API... except for linking, which no plugin exposes yet so I can't test it. --- .../AnyShaderConverter/AnyConverter.cpp | 17 ++++-- .../AnyShaderConverter/AnyConverter.h | 1 + .../Test/AnyConverterTest.cpp | 53 ++++++++++++++++++- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp index d37591974..76a96d70b 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp @@ -44,7 +44,7 @@ struct AnyConverter::State { Containers::Array> definitions; Containers::Array> definitionViews; - Containers::String debugInfoLevel; + Containers::String debugInfoLevel, optimizationLevel; }; AnyConverter::AnyConverter(PluginManager::Manager& manager): AbstractConverter{manager} {} @@ -54,8 +54,7 @@ AnyConverter::AnyConverter(PluginManager::AbstractManager& manager, const std::s AnyConverter::~AnyConverter() = default; ConverterFeatures AnyConverter::doFeatures() const { - /** @todo Optimize, also need checks that the plugin actually supports it */ - return ConverterFeature::ValidateFile|ConverterFeature::ConvertFile|ConverterFeature::Preprocess|ConverterFeature::DebugInfo; + return ConverterFeature::ValidateFile|ConverterFeature::ConvertFile|ConverterFeature::Preprocess|ConverterFeature::DebugInfo|ConverterFeature::Optimize; } void AnyConverter::doSetInputFormat(const Format format, const Containers::StringView version) { @@ -94,6 +93,10 @@ void AnyConverter::doSetDebugInfoLevel(const Containers::StringView level) { _state->debugInfoLevel = Containers::String::nullTerminatedGlobalView(level); } +void AnyConverter::doSetOptimizationLevel(const Containers::StringView level) { + _state->optimizationLevel = Containers::String::nullTerminatedGlobalView(level); +} + namespace { using namespace Containers::Literals; @@ -249,6 +252,12 @@ bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::Stri return {}; } + /* Check that it can optimize, in case we were asked to */ + if(!_state->optimizationLevel.isEmpty() && !(converter->features() & ConverterFeature::Optimize)) { + Error{} << "ShaderTools::AnyConverter::convertFileToFile():" << metadata->name() << "does not support optimization"; + return {}; + } + /* Propagate input/output version and flags */ converter->setFlags(flags()); converter->setInputFormat(_state->inputFormat, _state->inputVersion); @@ -259,6 +268,8 @@ bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::Stri 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) */ diff --git a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h index f5c07671f..965f1acd8 100644 --- a/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h +++ b/src/MagnumPlugins/AnyShaderConverter/AnyConverter.h @@ -135,6 +135,7 @@ class MAGNUM_ANYSHADERCONVERTER_EXPORT AnyConverter: public AbstractConverter { 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 void doSetOptimizationLevel(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 4d534e7bd..98a338c0d 100644 --- a/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp +++ b/src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp @@ -54,11 +54,13 @@ struct AnyConverterTest: TestSuite::Tester { void convertNotSupported(); void convertPreprocessNotSupported(); void convertDebugInfoNotSupported(); + void convertOptimizationNotSupported(); void convertPropagateFlags(); void convertPropagateInputVersion(); void convertPropagateOutputVersion(); void convertPropagatePreprocess(); void convertPropagateDebugInfo(); + void convertPropagateOptimization(); void detectValidate(); void detectConvert(); @@ -106,11 +108,13 @@ AnyConverterTest::AnyConverterTest() { &AnyConverterTest::convertNotSupported, &AnyConverterTest::convertPreprocessNotSupported, &AnyConverterTest::convertDebugInfoNotSupported, + &AnyConverterTest::convertOptimizationNotSupported, &AnyConverterTest::convertPropagateFlags, &AnyConverterTest::convertPropagateInputVersion, &AnyConverterTest::convertPropagateOutputVersion, &AnyConverterTest::convertPropagatePreprocess, - &AnyConverterTest::convertPropagateDebugInfo}); + &AnyConverterTest::convertPropagateDebugInfo, + &AnyConverterTest::convertPropagateOptimization}); addInstancedTests({&AnyConverterTest::detectValidate}, Containers::arraySize(DetectValidateData)); @@ -358,6 +362,29 @@ void AnyConverterTest::convertDebugInfoNotSupported() { "ShaderTools::AnyConverter::convertFileToFile(): SpirvToolsShaderConverter does not support controlling debug info output\n"); } +void AnyConverterTest::convertOptimizationNotSupported() { + 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->setOptimizationLevel("1"); + + std::ostringstream out; + Error redirectError{&out}; + CORRADE_VERIFY(!converter->convertFileToFile({}, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"), + Utility::Directory::join(ANYSHADERCONVERTER_TEST_OUTPUT_DIR, "file.spv"))); + /** @todo it once may support that, in which case we need to find another + victim */ + CORRADE_COMPARE(out.str(), + "ShaderTools::AnyConverter::convertFileToFile(): GlslangShaderConverter does not support optimization\n"); +} + void AnyConverterTest::convertPropagateFlags() { PluginManager::Manager manager{MAGNUM_PLUGINS_SHADERCONVERTER_INSTALL_DIR}; #ifdef ANYSHADERCONVERTER_PLUGIN_FILENAME @@ -494,6 +521,30 @@ void AnyConverterTest::convertPropagateDebugInfo() { "ShaderTools::GlslangConverter::convertDataToData(): debug info level should be 0, 1 or empty but got 2\n"); } +void AnyConverterTest::convertPropagateOptimization() { + 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"); + + /* 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->convertFileToFile(Stage::Fragment, Utility::Directory::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv"), Utility::Directory::join(ANYSHADERCONVERTER_TEST_OUTPUT_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);