mirror of https://github.com/mosra/magnum.git
35 changed files with 494 additions and 4 deletions
@ -0,0 +1,439 @@ |
|||||||
|
/*
|
||||||
|
This file is part of Magnum. |
||||||
|
|
||||||
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
||||||
|
2020 Vladimír Vondruš <mosra@centrum.cz> |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a |
||||||
|
copy of this software and associated documentation files (the "Software"), |
||||||
|
to deal in the Software without restriction, including without limitation |
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||||
|
and/or sell copies of the Software, and to permit persons to whom the |
||||||
|
Software is furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included |
||||||
|
in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||||
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||||
|
DEALINGS IN THE SOFTWARE. |
||||||
|
*/ |
||||||
|
|
||||||
|
#include <Corrade/Containers/GrowableArray.h> |
||||||
|
#include <Corrade/Utility/Arguments.h> |
||||||
|
#include <Corrade/Utility/DebugStl.h> |
||||||
|
#include <Corrade/Utility/Directory.h> |
||||||
|
#include <Corrade/Utility/String.h> |
||||||
|
|
||||||
|
#include "Magnum/Implementation/converterUtilities.h" |
||||||
|
#include "Magnum/Math/Functions.h" |
||||||
|
#include "Magnum/ShaderTools/AbstractConverter.h" |
||||||
|
|
||||||
|
namespace Magnum { |
||||||
|
|
||||||
|
/** @page magnum-shaderconverter Shader conversion utility
|
||||||
|
@brief Converts, compiles, optimizes and links shaders of different formats |
||||||
|
@m_since_latest |
||||||
|
|
||||||
|
@m_footernavigation |
||||||
|
@m_keywords{magnum-shaderconverter shaderconverter} |
||||||
|
|
||||||
|
This utility is built if both `WITH_SHADERTOOLS` and `WITH_SHADERCONVERTER` is |
||||||
|
enabled when building Magnum. To use this utility with CMake, you need to |
||||||
|
request the `shaderconverter` component of the `Magnum` package and use the |
||||||
|
`Magnum::shaderconverter` target for example in a custom command: |
||||||
|
|
||||||
|
@code{.cmake} |
||||||
|
find_package(Magnum REQUIRED shaderconverter) |
||||||
|
|
||||||
|
add_custom_command(OUTPUT ... COMMAND Magnum::shaderconverter ...) |
||||||
|
@endcode |
||||||
|
|
||||||
|
See @ref building, @ref cmake and the @ref ShaderTools namespace for more |
||||||
|
information. |
||||||
|
|
||||||
|
@section magnum-shaderconverter-usage Usage |
||||||
|
|
||||||
|
@code{.sh} |
||||||
|
magnum-shaderconverter [-h|--help] [--validate] [--link] |
||||||
|
[-C|--converter NAME]... [--plugin-dir DIR] |
||||||
|
[-c|--converter-options key=val,key2=val2,…]... [-q|--quiet] [-v|--verbose] |
||||||
|
[--warning-as-error] [-E|--preprocess-only] [-D|--define name=value]... |
||||||
|
[-U|--undefine name]... [-O|--optimize LEVEL] [-g|--debug-info LEVEL] |
||||||
|
[--input-version VERSION]... [--output-version VERSION]... |
||||||
|
[--] input... output |
||||||
|
@endcode |
||||||
|
|
||||||
|
Arguments: |
||||||
|
|
||||||
|
- `input` --- input file(s) |
||||||
|
- `output` --- output file, ignored if `--validate` is present |
||||||
|
- `-h`, `--help` --- display this help message and exit |
||||||
|
- `--validate` --- validate input |
||||||
|
- `--link` --- link multiple input files together |
||||||
|
- `-C`, `--converter CONVERTER` --- shader converter plugin(s) |
||||||
|
- `--plugin-dir DIR` --- override base plugin dir |
||||||
|
- `-c`, `--converter-options key=val,key2=val2,…` --- configuration options |
||||||
|
to pass to the converter(s) |
||||||
|
- `-q`, `--quiet` --- quiet output from converter plugin(s) |
||||||
|
- `-v`, `--verbose` --- verbose output from converter plugin(s) |
||||||
|
- `--warning-as-error` --- treat warnings as errors |
||||||
|
- `-E`, `--preprocess-only` --- preprocess the input file and exit |
||||||
|
- `-D`, `--define name=value` --- define a preprocessor macro |
||||||
|
- `-U`, `--undefine name` --- undefine a preprocessor macro |
||||||
|
- `-O`, `--optimize LEVEL` --- optimization level to use |
||||||
|
- `-g`, `--debug-info LEVEL` --- debug info level to use |
||||||
|
- `--input-version VERSION` --- input format version for each converter |
||||||
|
- `--output-version VERSION` --- output format version for each converter |
||||||
|
|
||||||
|
If `--validate` is given, the utility will validate the `input` file using |
||||||
|
passed `--converter` (or @ref ShaderTools::AnyConverter "AnyShaderConverter" if |
||||||
|
none is specified), print the validation log on output and exit with a non-zero |
||||||
|
code if the validation fails. If `--link` is given, the utility will link all |
||||||
|
files together using passed `--converter` (or |
||||||
|
@ref ShaderTools::AnyConverter "AnyShaderConverter" if none is specified) and |
||||||
|
save it to `output`. If neither is specified, the utility will convert the |
||||||
|
`input` file using (one or more) passed `--converter` (or |
||||||
|
@ref ShaderTools::AnyConverter "AnyShaderConverter" if none is specified) and |
||||||
|
save it to `output`. |
||||||
|
|
||||||
|
The `-c` / `--converter-options` argument accept a comma-separated list of |
||||||
|
key/value pairs to set in the converter plugin configuration. If the `=` |
||||||
|
character is omitted, it's equivalent to saying `key=true`; configuration |
||||||
|
subgroups are delimited with `/`. It's possible to specify the `-C` / |
||||||
|
`--converter` option (and correspondingly also `-c` / `--converter-options`, |
||||||
|
`--input-version` and `--output-version`) multiple times in order to chain more |
||||||
|
converters together. All converters in the chain have to support the |
||||||
|
@ref ShaderTools::ConverterFeature::ConvertData feature, if there's just one |
||||||
|
converter it's enough for it to support |
||||||
|
@ref ShaderTools::ConverterFeature::ConvertFile. If no `-C` / `--converter` is |
||||||
|
specified, @ref ShaderTools::AnyConverter "AnyShaderConverter" is used. |
||||||
|
|
||||||
|
The `-D` / `--define`, `-U` / `--undefine`, `-O` / `--optimize`, `-g` / |
||||||
|
`--debug-info`, `-E` / `--preprocess-only` arguments apply only to the first |
||||||
|
converter. Split the conversion to multiple passes if you need to pass those to |
||||||
|
converters later in the chain. |
||||||
|
|
||||||
|
Values accepted by `-O` / `--optimize`, `-g` / `--debug-info`, `--input-version` |
||||||
|
and `--output-version` are converter-specific, see documentation of a |
||||||
|
particular converter for more information. |
||||||
|
|
||||||
|
@section magnum-shaderconverter-example Example usage |
||||||
|
|
||||||
|
Validate a SPIR-V file for a Vulkan 1.1 target, using |
||||||
|
@ref ShaderTools::SpirvToolsConverter "SpirvToolsShaderConverter" picked by |
||||||
|
@ref ShaderTools::AnyConverter "AnyShaderConverter": |
||||||
|
|
||||||
|
@code{.sh} |
||||||
|
magnum-shaderconverter --validate --output-version vulkan1.1 shader.spv |
||||||
|
@endcode |
||||||
|
|
||||||
|
Converting a GLSL 4.10 file to a SPIR-V, supplying various preprocessor |
||||||
|
definitions, treating warnings as errors and targeting OpenGL instead of the |
||||||
|
(default) Vulkan, using @ref ShaderTools::GlslangConverter "GlslangShaderConverter" |
||||||
|
picked again by @ref ShaderTools::AnyConverter "AnyShaderConverter": |
||||||
|
|
||||||
|
@m_class{m-console-wrap} |
||||||
|
|
||||||
|
@code{.sh} |
||||||
|
magnum-shaderconverter phong.frag -DDIFFUSE_TEXTURE -DNORMAL_TEXTURE --input-version "410 core" --output-version opengl4.5 --warning-as-error phong.frag.spv |
||||||
|
@endcode |
||||||
|
*/ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
using namespace Magnum; |
||||||
|
|
||||||
|
int main(int argc, char** argv) { |
||||||
|
Utility::Arguments args; |
||||||
|
args.addArrayArgument("input").setHelp("input", "input file(s)") |
||||||
|
.addArgument("output").setHelp("output", "output file, ignored if --validate is present") |
||||||
|
.addBooleanOption("validate").setHelp("validate", "validate input") |
||||||
|
.addBooleanOption("link").setHelp("link", "link multiple input files together") |
||||||
|
.addArrayOption('C', "converter").setHelp("converter", "shader converter plugin(s)") |
||||||
|
.addOption("plugin-dir").setHelp("plugin-dir", "override base plugin dir", "DIR") |
||||||
|
.addArrayOption('c', "converter-options").setHelp("converter-options", "configuration options to pass to the converter(s)", "key=val,key2=val2,…") |
||||||
|
.addBooleanOption('q', "quiet").setHelp("quiet", "quiet output from converter plugin(s)") |
||||||
|
.addBooleanOption('v', "verbose").setHelp("verbose", "verbose output from converter plugin(s)") |
||||||
|
.addBooleanOption("warning-as-error").setHelp("warning-as-error", "treat warnings as errors") |
||||||
|
.addBooleanOption('E', "preprocess-only").setHelp("preprocess-only", "preprocess the input file and exit") |
||||||
|
.addArrayOption('D', "define").setHelp("define", "define a preprocessor macro", "name=value") |
||||||
|
.addArrayOption('U', "undefine").setHelp("undefine", "undefine a preprocessor macro", "name") |
||||||
|
.addOption('O', "optimize").setHelp("optimize", "optimization level to use", "LEVEL") |
||||||
|
.addOption('g', "debug-info").setHelp("debug-info", "debug info level to use", "LEVEL") |
||||||
|
.addArrayOption("input-version").setHelp("input-version", "input format version for each converter", "VERSION") |
||||||
|
.addArrayOption("output-version").setHelp("output-version", "output format version for each converter", "VERSION") |
||||||
|
.setParseErrorCallback([](const Utility::Arguments& args, Utility::Arguments::ParseError error, const std::string& key) { |
||||||
|
/* If --validate is passed, we don't need the output argument */ |
||||||
|
if(error == Utility::Arguments::ParseError::MissingArgument && |
||||||
|
key == "output" && args.isSet("validate")) return true; |
||||||
|
|
||||||
|
/* Handle all other errors as usual */ |
||||||
|
return false; |
||||||
|
}) |
||||||
|
.setGlobalHelp(R"(Converts, compiles, optimizes and links shaders of different formats. |
||||||
|
|
||||||
|
If --validate is given, the utility will validate the input file using passed |
||||||
|
--converter (or AnyShaderConverter if none is specified), print the validation |
||||||
|
log on output and exit with a non-zero code if the validation fails. If --link |
||||||
|
is given, the utility will link all files together using passed --converter (or |
||||||
|
AnyShaderConverter if none is specified) and save it to output. If neither is |
||||||
|
specified, the utility will convert the input file using (one or more) passed |
||||||
|
--converter and save it to output. |
||||||
|
|
||||||
|
The -c / --converter-options argument accept a comma-separated list of |
||||||
|
key/value pairs to set in the converter plugin configuration. If the = |
||||||
|
character is omitted, it's equivalent to saying key=true; configuration |
||||||
|
subgroups are delimited with /. It's possible to specify the -C / --converter |
||||||
|
option (and correspondingly also -c / --converter-options, --input-version and |
||||||
|
--output-version) multiple times in order to chain more converters together. |
||||||
|
All converters in the chain have to support the ConvertData feature, if there's |
||||||
|
just one converter it's enough for it to support ConvertFile. If no -C / |
||||||
|
--converter is specified, AnyShaderConverter is used. |
||||||
|
|
||||||
|
The -D / --define, -U / --undefine, -O / --optimize, -g / --debug-info, -E / |
||||||
|
--preprocess-only arguments apply only to the first converter. Split the |
||||||
|
conversion to multiple passes if you need to pass those to converters later in |
||||||
|
the chain. |
||||||
|
|
||||||
|
Values accepted by -O / --optimize, -g / --debug-info, --input-version and |
||||||
|
--output-version are converter-specific, see documentation of a particular |
||||||
|
converter for more information.)") |
||||||
|
.parse(argc, argv); |
||||||
|
|
||||||
|
/* Generic checks */ |
||||||
|
if(args.isSet("validate")) { |
||||||
|
if(!args.value("output").empty()) { |
||||||
|
Error{} << "Output file shouldn't be set for --validate"; |
||||||
|
return 1; |
||||||
|
} |
||||||
|
} |
||||||
|
if(!args.isSet("link")) { |
||||||
|
if(args.arrayValueCount("input") != 1) { |
||||||
|
Error{} << "Multiple input files are allowed only for --link"; |
||||||
|
return 3; |
||||||
|
} |
||||||
|
if(args.isSet("preprocess-only")) { |
||||||
|
Error{} << "The --preprocess-only option isn't allowed for --link"; |
||||||
|
return 4; |
||||||
|
} |
||||||
|
} |
||||||
|
if((args.isSet("validate") || args.isSet("link")) && args.arrayValueCount("converter") > 1) { |
||||||
|
Error{} << "Cannot use multiple converters with --validate or --link"; |
||||||
|
return 5; |
||||||
|
} |
||||||
|
if(args.isSet("quiet") && args.isSet("verbose")) { |
||||||
|
Error{} << "Can't set both --quiet and --verbose"; |
||||||
|
return 6; |
||||||
|
} |
||||||
|
if(args.isSet("quiet") && args.isSet("warning-as-error")) { |
||||||
|
Error{} << "Can't set both --quiet and --warning-as-error"; |
||||||
|
return 6; |
||||||
|
} |
||||||
|
|
||||||
|
/* Set up a converter manager */ |
||||||
|
PluginManager::Manager<ShaderTools::AbstractConverter> converterManager{ |
||||||
|
args.value("plugin-dir").empty() ? std::string{} : |
||||||
|
Utility::Directory::join(args.value("plugin-dir"), ShaderTools::AbstractConverter::pluginSearchPaths()[0])}; |
||||||
|
|
||||||
|
/* Data passed from one converter to another in case there's more than one */ |
||||||
|
Containers::Array<char> data; |
||||||
|
|
||||||
|
/* If there's no converters, it'll be just one AnyShaderConverter. */ |
||||||
|
for(std::size_t i = 0, converterCount = args.arrayValueCount("converter"); i < Math::max(converterCount, std::size_t{1}); ++i) { |
||||||
|
const std::string converterName = converterCount ? |
||||||
|
args.arrayValue("converter", i) : "AnyShaderConverter"; |
||||||
|
Containers::Pointer<ShaderTools::AbstractConverter> converter = converterManager.loadAndInstantiate(converterName); |
||||||
|
if(!converter) { |
||||||
|
Debug{} << "Available converter plugins:" << Utility::String::join(converterManager.aliasList(), ", "); |
||||||
|
return 7; |
||||||
|
} |
||||||
|
|
||||||
|
/* Set options and versions, if passed */ |
||||||
|
if(i < args.arrayValueCount("converter-options")) |
||||||
|
Implementation::setOptions(*converter, args.arrayValue("converter-options", i)); |
||||||
|
if(i < args.arrayValueCount("input-version")) |
||||||
|
converter->setInputFormat({}, args.arrayValue("input-version", i)); |
||||||
|
if(i < args.arrayValueCount("output-version")) |
||||||
|
converter->setOutputFormat({}, args.arrayValue("output-version", i)); |
||||||
|
|
||||||
|
ShaderTools::ConverterFlags flags; |
||||||
|
|
||||||
|
/* Global flags, applied for all converters */ |
||||||
|
if(args.isSet("quiet")) flags |= ShaderTools::ConverterFlag::Quiet; |
||||||
|
if(args.isSet("verbose")) flags |= ShaderTools::ConverterFlag::Verbose; |
||||||
|
if(args.isSet("warning-as-error")) flags |= ShaderTools::ConverterFlag::WarningAsError; |
||||||
|
|
||||||
|
/* Options and flags applied just for the first converter; setting up
|
||||||
|
file list for linking */ |
||||||
|
Containers::Array<std::pair<ShaderTools::Stage, Containers::StringView>> linkInputs; |
||||||
|
if(i == 0) { |
||||||
|
if((args.isSet("preprocess-only") || args.arrayValueCount("define") || args.arrayValueCount("undefine"))) { |
||||||
|
if(!(converter->features() & ShaderTools::ConverterFeature::Preprocess)) { |
||||||
|
Error{} << "The -E / -D / -U options are set, but" << converterName << "doesn't support preprocessing"; |
||||||
|
return 8; |
||||||
|
} |
||||||
|
|
||||||
|
if(args.isSet("preprocess-only")) |
||||||
|
flags |= ShaderTools::ConverterFlag::PreprocessOnly; |
||||||
|
|
||||||
|
Containers::Array<std::pair<Containers::StringView, Containers::StringView>> definitions; |
||||||
|
arrayReserve(definitions, args.arrayValueCount("define") + args.arrayValueCount("undefine")); |
||||||
|
for(std::size_t i = 0; i != args.arrayValueCount("define"); ++i) { |
||||||
|
const Containers::Array3<Containers::StringView> define = |
||||||
|
args.arrayValue<Containers::StringView>("define", i).partition('='); |
||||||
|
arrayAppend(definitions, Containers::InPlaceInit, |
||||||
|
define[0], define[2]); |
||||||
|
} |
||||||
|
for(std::size_t i = 0; i != args.arrayValueCount("undefine"); ++i) { |
||||||
|
arrayAppend(definitions, Containers::InPlaceInit, |
||||||
|
args.arrayValue<Containers::StringView>("undefine", i), nullptr); |
||||||
|
} |
||||||
|
|
||||||
|
converter->setDefinitions(definitions); |
||||||
|
} |
||||||
|
|
||||||
|
if(!args.value("optimize").empty()) { |
||||||
|
if(!(converter->features() & ShaderTools::ConverterFeature::Optimize)) { |
||||||
|
Error{} << "The -O option is set, but" << converterName << "doesn't support optimization"; |
||||||
|
return 9; |
||||||
|
} |
||||||
|
|
||||||
|
converter->setOptimizationLevel(args.value("optimize")); |
||||||
|
} |
||||||
|
|
||||||
|
if(!args.value("debug-info").empty()) { |
||||||
|
if(!(converter->features() & ShaderTools::ConverterFeature::DebugInfo)) { |
||||||
|
Error{} << "The -g option is set, but" << converterName << "doesn't support debug info"; |
||||||
|
return 10; |
||||||
|
} |
||||||
|
|
||||||
|
converter->setDebugInfoLevel(args.value("debug-info")); |
||||||
|
} |
||||||
|
|
||||||
|
if(args.isSet("link")) { |
||||||
|
arrayReserve(linkInputs, args.arrayValueCount("input")); |
||||||
|
for(std::size_t i = 0; i != args.arrayValueCount("input"); ++i) |
||||||
|
arrayAppend(linkInputs, Containers::InPlaceInit, |
||||||
|
ShaderTools::Stage::Unspecified, args.arrayValue("input", i)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
converter->setFlags(flags); |
||||||
|
|
||||||
|
/* If validating, do it just with the first passed converter and then
|
||||||
|
exit */ |
||||||
|
if(args.isSet("validate")) { |
||||||
|
/* The validation exits right after, so this branch shouldn't get
|
||||||
|
re-entered again */ |
||||||
|
CORRADE_INTERNAL_ASSERT(i == 0); |
||||||
|
|
||||||
|
if(!(converter->features() & ShaderTools::ConverterFeature::ValidateFile)) { |
||||||
|
Error{} << converterName << "doesn't support file validation"; |
||||||
|
return 11; |
||||||
|
} |
||||||
|
|
||||||
|
std::pair<bool, Containers::String> out = converter->validateFile(ShaderTools::Stage::Unspecified, args.arrayValue("input", 0)); |
||||||
|
if(!out.first) { |
||||||
|
if(args.isSet("verbose")) |
||||||
|
Error{} << "Validation failed:"; |
||||||
|
if(!out.second.isEmpty()) Error{} << out.second; |
||||||
|
} else if(!out.second.isEmpty()) { |
||||||
|
if(args.isSet("verbose")) |
||||||
|
Warning{} << "Validation succeeded with warnings:"; |
||||||
|
if(!out.second.isEmpty()) Warning{} << out.second; |
||||||
|
} else if(args.isSet("verbose")) |
||||||
|
Debug{} << "Validation passed"; |
||||||
|
return out.first ? 0 : 12; |
||||||
|
} |
||||||
|
|
||||||
|
/** @todo ability to specify the stage (need a configurationvalue parser for this) */ |
||||||
|
|
||||||
|
/* This is the first *and* last --converter, go from a file to a file */ |
||||||
|
if(i == 0 && converterCount <= 1) { |
||||||
|
if(!(converter->features() & ShaderTools::ConverterFeature::ConvertFile)) { |
||||||
|
Error{} << converterName << "doesn't support file conversion"; |
||||||
|
return 13; |
||||||
|
} |
||||||
|
|
||||||
|
/* No verbose output for just one converter */ |
||||||
|
|
||||||
|
/* Linking */ |
||||||
|
if(args.isSet("link")) { |
||||||
|
if(!converter->linkFilesToFile(linkInputs, args.value("output"))) { |
||||||
|
Error{} << "Cannot link" << args.arrayValue("input", 0) << "and others to" << args.value("output"); |
||||||
|
return 14; |
||||||
|
} |
||||||
|
|
||||||
|
/* Converting */ |
||||||
|
} else { |
||||||
|
if(!converter->convertFileToFile(ShaderTools::Stage::Unspecified, args.arrayValue("input", 0), args.value("output"))) { |
||||||
|
Error{} << "Cannot convert" << args.arrayValue("input", 0) << "to" << args.value("output"); |
||||||
|
return 15; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Otherwise we need to go through data */ |
||||||
|
} else { |
||||||
|
if(!(converter->features() & ShaderTools::ConverterFeature::ConvertData)) { |
||||||
|
Error{} << converterName << "doesn't support data conversion"; |
||||||
|
return 16; |
||||||
|
} |
||||||
|
|
||||||
|
/* This is the first --converter and there are more, go from a file
|
||||||
|
to data */ |
||||||
|
if(i == 0 && converterCount > 1) { |
||||||
|
if(args.isSet("verbose")) |
||||||
|
Debug{} << "Processing (" << Debug::nospace << (i+1) << Debug::nospace << "/" << Debug::nospace << converterCount << Debug::nospace << ") with" << converterName << Debug::nospace << "..."; |
||||||
|
|
||||||
|
/* Linking */ |
||||||
|
if(args.isSet("link")) { |
||||||
|
if(!(data = converter->linkFilesToData(linkInputs))) { |
||||||
|
Error{} << "Cannot link" << args.arrayValue("input", 0) << "and others to" << args.value("output"); |
||||||
|
return 17; |
||||||
|
} |
||||||
|
|
||||||
|
/* Converting */ |
||||||
|
} else { |
||||||
|
if(!(data = converter->convertFileToData(ShaderTools::Stage::Unspecified, args.arrayValue("input", 0)))) { |
||||||
|
Error{} << "Cannot convert" << args.arrayValue("input", 0); |
||||||
|
return 18; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* This is neither first nor last --converter, go from data to
|
||||||
|
data */ |
||||||
|
} else if(i > 0 && i + 1 < converterCount) { |
||||||
|
if(args.isSet("verbose")) |
||||||
|
Debug{} << "Processing (" << Debug::nospace << (i+1) << Debug::nospace << "/" << Debug::nospace << converterCount << Debug::nospace << ") with" << converterName << Debug::nospace << "..."; |
||||||
|
|
||||||
|
CORRADE_INTERNAL_ASSERT(data); |
||||||
|
|
||||||
|
/* Subsequent operations are always a conversion, not link */ |
||||||
|
if(!(data = converter->convertDataToData(ShaderTools::Stage::Unspecified, data))) { |
||||||
|
Error{} << "Cannot convert shader data"; |
||||||
|
return 19; |
||||||
|
} |
||||||
|
|
||||||
|
/* This is the last --converter, output to a file and exit the
|
||||||
|
loop */ |
||||||
|
} else if(i + 1 >= converterCount) { |
||||||
|
if(args.isSet("verbose")) |
||||||
|
Debug{} << "Saving output with" << converterName << Debug::nospace << "..."; |
||||||
|
|
||||||
|
CORRADE_INTERNAL_ASSERT(data); |
||||||
|
|
||||||
|
/* Subsequent operations are always a conversion, not link */ |
||||||
|
if(!converter->convertDataToFile(ShaderTools::Stage::Unspecified, data, args.value("output"))) { |
||||||
|
Error{} << "Cannot save file" << args.value("output"); |
||||||
|
return 20; |
||||||
|
} |
||||||
|
|
||||||
|
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue