mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1245 lines
57 KiB
1245 lines
57 KiB
#ifndef Magnum_ShaderTools_AbstractConverter_h |
|
#define Magnum_ShaderTools_AbstractConverter_h |
|
/* |
|
This file is part of Magnum. |
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, |
|
2020, 2021, 2022, 2023, 2024, 2025 |
|
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. |
|
*/ |
|
|
|
/** @file |
|
* @brief Class @ref Magnum::ShaderTools::AbstractConverter, enum @ref Magnum::ShaderTools::ConverterFeature, @ref Magnum::ShaderTools::ConverterFlag, @ref Magnum::ShaderTools::Format, enum set @ref Magnum::ShaderTools::ConverterFeatures, @ref Magnum::ShaderTools::ConverterFlags |
|
* @m_since_latest |
|
*/ |
|
|
|
#include <initializer_list> |
|
#include <Corrade/Containers/EnumSet.h> |
|
#include <Corrade/PluginManager/AbstractManagingPlugin.h> |
|
#include <Corrade/Utility/StlForwardString.h> /** @todo remove once file callbacks are std::string-free */ |
|
|
|
#include "Magnum/Magnum.h" |
|
#include "Magnum/ShaderTools/ShaderTools.h" |
|
#include "Magnum/ShaderTools/visibility.h" |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
/* For *ToData() APIs that used to return just an Array before */ |
|
#include <Corrade/Containers/Optional.h> |
|
|
|
/* For validate*() that used to return a std::pair. Similar case is with |
|
setDefinitions(), there a hope is that a std::initializer_list was used and |
|
thus the type change won't break much code; lastly the link APIs that used |
|
std::pair heavily are not implemented by any plugin yet so changing them |
|
should be still fine. */ |
|
#include <Corrade/Containers/PairStl.h> |
|
|
|
#include "Magnum/ShaderTools/Stage.h" |
|
#endif |
|
|
|
namespace Magnum { namespace ShaderTools { |
|
|
|
/** |
|
@brief Features supported by a shader converter |
|
@m_since_latest |
|
|
|
@see @ref ConverterFeatures, @ref AbstractConverter::features() |
|
*/ |
|
enum class ConverterFeature: UnsignedInt { |
|
/** |
|
* Validate shader file with @ref AbstractConverter::validateFile() |
|
*/ |
|
ValidateFile = 1 << 0, |
|
|
|
/** |
|
* Validate shader data with @ref AbstractConverter::validateData(). |
|
* Implies @ref ConverterFeature::ValidateData. |
|
*/ |
|
ValidateData = ValidateFile|(1 << 1), |
|
|
|
/** |
|
* Convert shader file to a file with @ref AbstractConverter::convertFileToFile() |
|
*/ |
|
ConvertFile = 1 << 2, |
|
|
|
/** |
|
* Convert shader data to data with |
|
* @ref AbstractConverter::convertDataToData() or any of the other |
|
* @ref AbstractConverter::convertDataToFile(), |
|
* @ref AbstractConverter::convertFileToData() combinations. Implies |
|
* @ref ConverterFeature::ConvertFile. |
|
*/ |
|
ConvertData = ConvertFile|(1 << 3), |
|
|
|
/** |
|
* Link shader files together and output a file with |
|
* @ref AbstractConverter::linkFilesToFile() |
|
*/ |
|
LinkFile = 1 << 4, |
|
|
|
/** |
|
* Link shader data together and output a data with |
|
* @ref AbstractConverter::linkDataToData() or any of the other |
|
* @ref AbstractConverter::linkDataToFile(), |
|
* @ref AbstractConverter::linkFilesToData() combinations. Implies |
|
* @ref ConverterFeature::LinkFile. |
|
*/ |
|
LinkData = LinkFile|(1 << 5), |
|
|
|
/** |
|
* Specifying input file callbacks for additional files referenced from the |
|
* main file using @ref AbstractConverter::setInputFileCallback(). If the |
|
* converter doesn't expose this feature, the format is either single-file |
|
* or input file callbacks are not supported. |
|
* |
|
* See @ref ShaderTools-AbstractConverter-usage-callbacks and particular |
|
* converter documentation for more information. |
|
*/ |
|
InputFileCallback = 1 << 6, |
|
|
|
/** |
|
* Set preprocess definitions using @ref AbstractConverter::setDefinitions() |
|
* and the @ref ConverterFlag::PreprocessOnly flag. |
|
*/ |
|
Preprocess = 1 << 7, |
|
|
|
/** |
|
* Control code optimization using |
|
* @ref AbstractConverter::setOptimizationLevel() |
|
*/ |
|
Optimize = 1 << 8, |
|
|
|
/** |
|
* Control amount of debug info present in the output using |
|
* @ref AbstractConverter::setDebugInfoLevel() |
|
*/ |
|
DebugInfo = 1 << 9 |
|
}; |
|
|
|
/** |
|
@brief Features supported by a shader converter |
|
@m_since_latest |
|
|
|
@see @ref AbstractConverter::features() |
|
*/ |
|
typedef Containers::EnumSet<ConverterFeature> ConverterFeatures; |
|
|
|
CORRADE_ENUMSET_OPERATORS(ConverterFeatures) |
|
|
|
/** |
|
@debugoperatorenum{ConverterFeature} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFeature value); |
|
|
|
/** |
|
@debugoperatorenum{ConverterFeatures} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFeatures value); |
|
|
|
/** |
|
@brief Shader converter flag |
|
@m_since_latest |
|
|
|
@see @ref ConverterFlags, @ref AbstractConverter::setFlags() |
|
*/ |
|
enum class ConverterFlag: UnsignedInt { |
|
/** |
|
* Suppress warnings, print just errors. By default the converter prints |
|
* both warnings and errors. Corresponds to the `-q` / `--quiet` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
* @see @ref ConverterFlag::WarningAsError |
|
*/ |
|
Quiet = 1 << 0, |
|
|
|
/** |
|
* Print verbose diagnostic. By default the converter only prints warnings |
|
* and errors. Corresponds to the `-v` / `--verbose` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
*/ |
|
Verbose = 1 << 1, |
|
|
|
/** |
|
* Treat warnings as error. By default, if a warning occurs, |
|
* validation or conversion succeeds. With this flag set, it fails. |
|
* Corresponds to the `--warning-as-error` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
* @see @ref ConverterFlag::Quiet |
|
*/ |
|
WarningAsError = 1 << 2, |
|
|
|
/** |
|
* Only run the preprocessor. Available only if the converter supports |
|
* @ref ConverterFeature::Preprocess, not allowed in combination with |
|
* @ref AbstractConverter::linkDataToData(), |
|
* @ref AbstractConverter::linkDataToFile(), |
|
* @ref AbstractConverter::linkFilesToFile() or |
|
* @ref AbstractConverter::linkFilesToData(). Corresponds to the `-E` / |
|
* `--preprocess-only` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
*/ |
|
PreprocessOnly = 1 << 3 |
|
}; |
|
|
|
/** |
|
@brief Shader converter flags |
|
@m_since_latest |
|
|
|
@see @ref AbstractConverter::setFlags() |
|
*/ |
|
typedef Containers::EnumSet<ConverterFlag> ConverterFlags; |
|
|
|
CORRADE_ENUMSET_OPERATORS(ConverterFlags) |
|
|
|
/** |
|
@debugoperatorenum{ConverterFlag} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFlag value); |
|
|
|
/** |
|
@debugoperatorenum{ConverterFlags} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFlags value); |
|
|
|
/** |
|
@brief Shader format |
|
@m_since_latest |
|
|
|
Describes input and output shader format. |
|
@see @ref AbstractConverter::setInputFormat(), |
|
@ref AbstractConverter::setOutputFormat() |
|
*/ |
|
enum class Format: UnsignedInt { |
|
/** |
|
* Either leaves format detection up to the implementation or describes a |
|
* format not fitting into any other categories. This includes various |
|
* application-specific languages and language flavors, compressed or |
|
* encrypted data and other. |
|
* |
|
* This value is guaranteed to be @cpp 0 @ce, which means you're encouraged |
|
* to simply use @cpp {} @ce in function calls and elsewhere. |
|
*/ |
|
Unspecified = 0, |
|
|
|
/** [GLSL](https://en.wikipedia.org/wiki/OpenGL_Shading_Language) */ |
|
Glsl, |
|
|
|
/** [SPIR-V](https://en.wikipedia.org/wiki/Standard_Portable_Intermediate_Representation#SPIR-V) */ |
|
Spirv, |
|
|
|
/** |
|
* Textual representation of [SPIR-V](https://en.wikipedia.org/wiki/Standard_Portable_Intermediate_Representation#SPIR-V). |
|
*/ |
|
SpirvAssembly, |
|
|
|
/** |
|
* [HLSL](https://en.wikipedia.org/wiki/High-Level_Shading_Language) |
|
* (High-Level Shading Language), used in D3D |
|
*/ |
|
Hlsl, |
|
|
|
/** |
|
* [MSL](https://en.wikipedia.org/wiki/Metal_(API)) (Metal Shading |
|
* Language) |
|
*/ |
|
Msl, |
|
|
|
/** |
|
* [WGSL](https://en.wikipedia.org/wiki/WebGPU) (WebGPU Shading Language) |
|
*/ |
|
Wgsl, |
|
|
|
/** |
|
* DXIL (DirectX Intermediate Language), produced by |
|
* [DirectX Shader Compiler](https://github.com/microsoft/DirectXShaderCompiler) |
|
*/ |
|
Dxil |
|
}; |
|
|
|
/** |
|
@debugoperatorenum{Format} |
|
@m_since_latest |
|
*/ |
|
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, Format value); |
|
|
|
#ifdef MAGNUM_BUILD_DEPRECATED |
|
namespace Implementation { |
|
/* Could be a concrete type as it's always only char, but that would mean |
|
I'd need to include Optional and Array here. There's a copy of this |
|
class for Trade::AbstractSceneConverter and AbstractImageConverter as |
|
introducing a common header containing just deprecated functionality |
|
seems silly. */ |
|
template<class T> struct OptionalButAlsoArray: Containers::Optional<Containers::Array<T>> { |
|
/*implicit*/ OptionalButAlsoArray() = default; |
|
/*implicit*/ OptionalButAlsoArray(Containers::Optional<Containers::Array<T>>&& optional): Containers::Optional<Containers::Array<T>>{Utility::move(optional)} {} |
|
CORRADE_DEPRECATED("use Containers::Optional<Containers::Array<T>> instead") /*implicit*/ operator Containers::Array<T>() && { |
|
return *this ? Containers::Array<T>{Utility::move(**this)} : nullptr; |
|
} |
|
}; |
|
} |
|
#endif |
|
|
|
/** |
|
@brief Base for shader converter plugins |
|
@m_since_latest |
|
|
|
@m_keywords{AbstractShaderConverter} |
|
|
|
Provides functionality for validating and converting shader code between |
|
different representations or performing optimizations and other operations on |
|
them. |
|
|
|
The interface supports three main kinds of operation, with implementations |
|
advertising support for a subset of them via @ref features(): |
|
|
|
- Shader validation using @ref validateFile() / @ref validateData(). Checking |
|
for compile errors, against platform limits etc. Advertised with |
|
@ref ConverterFeature::ValidateFile / @ref ConverterFeature::ValidateData. |
|
- Shader conversion using @ref convertFileToFile() / @ref convertFileToData() |
|
/ @ref convertDataToData(). Most commonly compilation of source code to an |
|
immediate representation but also (dis)assembly, transpiling or |
|
optimization. Advertised with @ref ConverterFeature::ConvertFile / |
|
@ref ConverterFeature::ConvertData. |
|
- Linking shaders together using @ref linkFilesToFile() / @ref linkFilesToData() |
|
/ @ref linkDataToData(). For example combining code for multiple shader |
|
stages into a single binary with deduplicated definitions of common inputs |
|
and outputs. Advertised with @ref ConverterFeature::LinkFile / |
|
@ref ConverterFeature::LinkData. |
|
|
|
@section ShaderTools-AbstractConverter-usage Usage |
|
|
|
Shader converters are most commonly implemented as plugins, which means the |
|
concrete converter implementation is loaded and instantiated through a |
|
@relativeref{Corrade,PluginManager::Manager}. See @ref plugins for more |
|
information about general plugin usage, @ref file-formats to compare |
|
implementations for common file formats and the list of |
|
@m_class{m-doc} <a href="#derived-classes">derived classes</a> for all |
|
available shader converter plugins. |
|
|
|
As each converter has different requirements on the source, its format and |
|
options set, you're expected to perform error handling on the application side |
|
--- if a conversion or linking fails, you get an empty |
|
@relativeref{Corrade,Containers::Optional} or @cpp false @ce and a reason |
|
printed to @relativeref{Magnum,Error}. Everything else (using a feature not |
|
implemented in the converter, ...) is treated as a programmer error and will |
|
produce the usual assertions. |
|
|
|
@m_class{m-note m-success} |
|
|
|
@par |
|
There's also the @ref magnum-shaderconverter "magnum-shaderconverter" tool |
|
that exposes functionality of all shader converter plugins through a |
|
command line interface. |
|
|
|
<b></b> |
|
|
|
@m_class{m-block m-warning} |
|
|
|
@par Multiple shader sources |
|
Compared to the (very broad) OpenGL API, only one shader source can be |
|
specified for a single stage. If you need to pass additional preprocessor |
|
flags, it's possible to do it via @ref setDefinitions() for plugins that |
|
support @ref ConverterFeature::Preprocess; if you have shader source |
|
scattered across multiple files either concatenate them together before |
|
processing or @cpp #include @ce the dependencies from the top-level file, |
|
potentially together with setting up @ref ShaderTools-AbstractConverter-usage-callbacks "file callbacks" |
|
(providing the particular converter implementation supports preprocessor |
|
includes). |
|
|
|
@subsection ShaderTools-AbstractConverter-usage-validation Shader validation |
|
|
|
As is common with other plugin interfaces, the |
|
@ref AnyConverter "AnyShaderConverter" will detect a shader format based on |
|
file extension, load an appropriate validator plugin for given format and |
|
validate it: |
|
|
|
@snippet ShaderTools.cpp AbstractConverter-usage-validation |
|
|
|
In most cases, the validation result depends on the format version and target |
|
environment used. Formats and versions set by @ref setInputFormat() / |
|
@ref setOutputFormat() get propagated by @ref AnyConverter "AnyShaderConverter" |
|
to the particular plugin, however the interpretation is plugin-specific, so be |
|
sure to read their docs. |
|
|
|
@subsection ShaderTools-AbstractConverter-usage-conversion Shader conversion and linking |
|
|
|
The following example shows converting a GLSL shader to SPIR-V together with |
|
setting preprocessor defines and treating any warnings as errors. This time |
|
it's not using @ref AnyConverter "AnyShaderConverter" but instead asking for a |
|
plugin using the `GlslToSpirvShaderConverter` alias (which maps for example to |
|
@ref GlslangConverter "GlslangShaderConverter") --- since we're operating |
|
directly on data, the plugin would have no chance to know the desired input / |
|
output format otherwise. Same goes for the shader stage, which has to be |
|
supplied explicitly: |
|
|
|
@snippet ShaderTools.cpp AbstractConverter-usage-compilation |
|
|
|
@todoc document linking when SpirvToolsShaderConverter implements that |
|
|
|
@subsection ShaderTools-AbstractConverter-usage-callbacks Loading shaders from memory, using file callbacks |
|
|
|
Besides loading shaders directly from the filesystem using @ref validateFile() |
|
/ @ref convertFileToFile() / @ref linkFilesToFile() like shown above, it's |
|
possible to use @ref validateData(), @ref convertDataToData(), |
|
@ref linkDataToData() and variants to load data from memory. Note that the |
|
particular converter implementation has to support |
|
@ref ConverterFeature::ValidateData / @ref ConverterFeature::ConvertData / |
|
@ref ConverterFeature::LinkData for this method to work. |
|
|
|
Textual shader sources sometimes @cpp #include @ce other sources and in that |
|
case you may want to intercept those references and load them in a custom way |
|
as well. For converters that advertise support for this with |
|
@ref ConverterFeature::InputFileCallback this is done by specifying an input |
|
file callback using @ref setInputFileCallback(). The callback gets a filename, |
|
@ref InputFileCallbackPolicy and an user pointer as parameters; returns a |
|
non-owning view on the loaded data or a |
|
@ref Corrade::Containers::NullOpt "Containers::NullOpt" to indicate the file |
|
loading failed. For example, validating a shader from compiled-in resources |
|
could look like below. Note that the input file callback affects |
|
@ref validateFile() / @ref convertFileToFile() / @ref convertFileToData() / |
|
@ref linkFilesToFile() / @ref linkFilesToData() as well --- you don't have to |
|
load the top-level file manually and pass it to @ref validateData() / |
|
@ref convertDataToData() / @ref linkDataToData(), any converter supporting the |
|
callback feature handles that correctly. |
|
|
|
@snippet ShaderTools.cpp AbstractConverter-usage-callbacks |
|
|
|
For converters that don't support @ref ConverterFeature::InputFileCallback |
|
directly, the base @ref validateFile() / @ref convertFileToFile() / |
|
@ref convertFileToData() / @ref linkFilesToFile() / @ref linkFilesToData() |
|
implementations will use the file callback to pass the loaded data through to |
|
@ref validateData() / @ref convertDataToData() / @ref linkDataToData(), in case |
|
the converter supports at least @ref ConverterFeature::ValidateData |
|
/ @ref ConverterFeature::ConvertData / @ref ConverterFeature::LinkData. If the |
|
converter supports none of @ref ConverterFeature::InputFileCallback, |
|
@ref ConverterFeature::ValidateData, @ref ConverterFeature::ConvertData or |
|
@ref ConverterFeature::LinkData, @ref setInputFileCallback() doesn't allow the |
|
callbacks to be set. |
|
|
|
The input file callback signature is the same for |
|
@ref ShaderTools::AbstractConverter, @ref Trade::AbstractImporter and |
|
@ref Text::AbstractFont to allow code reuse. |
|
|
|
@section ShaderTools-AbstractConverter-data-dependency Data dependency |
|
|
|
The instances returned from various functions *by design* have no dependency on |
|
the importer instance and neither on the dynamic plugin module. In other words, |
|
you don't need to keep the importer instance (or the plugin manager instance) |
|
around in order to have the returned data valid --- all returned |
|
@ref Corrade::Containers::String and @ref Corrade::Containers::Array instances |
|
are only allowed to have default deleters and this is to avoid potential |
|
dangling function pointer calls when destructing such instances after the |
|
plugin module has been unloaded. |
|
|
|
@section ShaderTools-AbstractConverter-subclassing Subclassing |
|
|
|
The plugin needs to implement the @ref doFeatures() function and one or more of |
|
@ref doValidateData(), @ref doValidateFile(), @ref doConvertDataToData(), |
|
@ref doConvertFileToData(), @ref doConvertFileToFile(), |
|
@ref doLinkDataToData(), @ref doLinkFilesToData() or @ref doLinkFilesToFile() |
|
functions based on what features are supported. |
|
|
|
You don't need to do most of the redundant sanity checks, these things are |
|
checked by the implementation: |
|
|
|
- The function @ref doValidateData() is called only if |
|
@ref ConverterFeature::ValidateData is supported. |
|
- The function @ref doValidateFile() is called only if |
|
@ref ConverterFeature::ValidateFile is supported. |
|
- Functions @ref doConvertDataToData() and @ref doConvertFileToData() are |
|
called only if @ref ConverterFeature::ConvertData is supported. |
|
- The function @ref doConvertFileToFile() is called only if |
|
@ref ConverterFeature::ConvertFile is supported. |
|
- Functions @ref doLinkDataToData() and @ref doLinkFilesToData() are |
|
called only if @ref ConverterFeature::LinkData is supported. |
|
- The function @ref doLinkFilesToFile() is called only if |
|
@ref ConverterFeature::LinkFile is supported. |
|
- Functions @ref doLinkDataToData(), @ref doLinkFilesToData() and |
|
@ref doLinkFilesToFile() are called only if the data / file list passed is |
|
non-empty. |
|
|
|
@m_class{m-block m-warning} |
|
|
|
@par Dangling function pointers on plugin unload |
|
As @ref ShaderTools-AbstractConverter-data-dependency "mentioned above", |
|
@ref Corrade::Containers::String and @ref Corrade::Containers::Array |
|
instances returned from plugin implementations are not allowed to use |
|
anything else than the default deleter, otherwise this could cause dangling |
|
function pointer call on array destruction if the plugin gets unloaded |
|
before the array is destroyed. This is asserted by the base implementation |
|
on return. |
|
*/ |
|
class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::AbstractManagingPlugin<AbstractConverter> { |
|
public: |
|
/** |
|
* @brief Plugin interface |
|
* |
|
* @snippet Magnum/ShaderTools/AbstractConverter.h interface |
|
* |
|
* @see @ref MAGNUM_SHADERTOOLS_ABSTRACTCONVERTER_PLUGIN_INTERFACE |
|
*/ |
|
static Containers::StringView pluginInterface(); |
|
|
|
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT |
|
/** |
|
* @brief Plugin search paths |
|
* |
|
* Looks into `magnum/shaderconverters/` or `magnum-d/shaderconverters/` |
|
* next to the dynamic @ref ShaderTools library, next to the executable |
|
* and elsewhere according to the rules documented in |
|
* @ref Corrade::PluginManager::implicitPluginSearchPaths(). The search |
|
* directory can be also hardcoded using the `MAGNUM_PLUGINS_DIR` CMake |
|
* variables, see @ref building for more information. |
|
* |
|
* Not defined on platforms without |
|
* @ref CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT "dynamic plugin support". |
|
*/ |
|
static Containers::Array<Containers::String> pluginSearchPaths(); |
|
#endif |
|
|
|
/** @brief Default constructor */ |
|
explicit AbstractConverter(); |
|
|
|
/** @brief Constructor with access to plugin manager */ |
|
explicit AbstractConverter(PluginManager::Manager<AbstractConverter>& manager); |
|
|
|
/** @brief Plugin manager constructor */ |
|
/* The plugin name is passed as a const& to make it possible for people |
|
to implement plugins without even having to include the StringView |
|
header. */ |
|
explicit AbstractConverter(PluginManager::AbstractManager& manager, const Containers::StringView& plugin); |
|
|
|
/** @brief Features supported by this converter */ |
|
ConverterFeatures features() const; |
|
|
|
/** @brief Converter flags */ |
|
ConverterFlags flags() const { return _flags; } |
|
|
|
/** |
|
* @brief Set converter flags |
|
* |
|
* Some flags can be set only if the converter supports particular |
|
* features, see documentation of each @ref ConverterFlag for more |
|
* information. By default no flags are set. To avoid clearing |
|
* potential future default flags by accident, prefer to use |
|
* @ref addFlags() and @ref clearFlags() instead. |
|
* |
|
* Corresponds to the `-q` / `--quiet`, `-v` / `--verbose`, |
|
* `--warning-as-error` and `-E` / `--preprocess-only` options |
|
* in @ref magnum-shaderconverter "magnum-shaderconverter". |
|
*/ |
|
void setFlags(ConverterFlags flags); |
|
|
|
/** |
|
* @brief Add converter flags |
|
* @m_since_latest |
|
* |
|
* Calls @ref setFlags() with the existing flags ORed with @p flags. |
|
* Useful for preserving the defaults. |
|
* @see @ref clearFlags() |
|
*/ |
|
void addFlags(ConverterFlags flags); |
|
|
|
/** |
|
* @brief Clear converter flags |
|
* @m_since_latest |
|
* |
|
* Calls @ref setFlags() with the existing flags ANDed with inverse of |
|
* @p flags. Useful for removing default flags. |
|
* @see @ref addFlags() |
|
*/ |
|
void clearFlags(ConverterFlags flags); |
|
|
|
/** |
|
* @brief Input file callback function |
|
* |
|
* @see @ref ShaderTools-AbstractConverter-usage-callbacks |
|
*/ |
|
auto inputFileCallback() const -> Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*) { return _inputFileCallback; } |
|
|
|
/** |
|
* @brief Input file callback user data |
|
* |
|
* @see @ref ShaderTools-AbstractConverter-usage-callbacks |
|
*/ |
|
void* inputFileCallbackUserData() const { return _inputFileCallbackUserData; } |
|
|
|
/** |
|
* @brief Set input file callback |
|
* |
|
* In case the converter supports @ref ConverterFeature::InputFileCallback, |
|
* files opened through @ref validateFile(), @ref convertFileToData(), |
|
* @ref convertFileToFile(), @ref linkFilesToData() and |
|
* @ref linkFilesToFile() will be loaded through the provided callback. |
|
* Besides that, all external files referenced by the top-level file |
|
* will be loaded through the callback function as well, usually on |
|
* demand. The callback function gets a filename, |
|
* @ref InputFileCallbackPolicy and the @p userData pointer as input |
|
* and returns a non-owning view on the loaded data as output or a |
|
* @ref Corrade::Containers::NullOpt if loading failed --- because |
|
* empty files might also be valid in some circumstances, |
|
* @cpp nullptr @ce can't be used to indicate a failure. |
|
* |
|
* In case the converter doesn't support |
|
* @ref ConverterFeature::InputFileCallback but supports at least |
|
* @ref ConverterFeature::ValidateData / |
|
* @ref ConverterFeature::ConvertData / |
|
* @ref ConverterFeature::LinkData, a file opened through |
|
* @ref validateFile(), @ref convertFileToData(), |
|
* @ref convertFileToFile(), @ref linkFilesToData() or |
|
* @ref linkFilesToFile() will be internally loaded through the |
|
* provided callback and then passed to @ref validateData(), |
|
* @ref convertDataToData() or @ref linkDataToData(). First the file is |
|
* loaded with @ref InputFileCallbackPolicy::LoadTemporary passed to |
|
* the callback, then the returned memory view is passed to |
|
* @ref validateData() / @ref convertDataToData() / |
|
* @ref linkDataToData() (sidestepping the potential |
|
* @ref validateFile() / @ref convertFileToFile() / |
|
* @ref convertFileToData() / @ref linkFilesToFile() / |
|
* @ref linkFilesToData() implementation of that particular converter) |
|
* and after that the callback is called again with |
|
* @ref InputFileCallbackPolicy::Close. In case you need a different |
|
* behavior, use @ref validateData() / @ref convertDataToData() / |
|
* @ref linkDataToData() directly. |
|
* |
|
* In case @p callback is @cpp nullptr @ce, the current callback (if |
|
* any) is reset. This function expects that the converter supports |
|
* either @ref ConverterFeature::InputFileCallback or at least one of |
|
* @ref ConverterFeature::ValidateData, |
|
* @ref ConverterFeature::ConvertData, @ref ConverterFeature::LinkData. |
|
* If a converter supports neither, callbacks can't be used. |
|
* |
|
* Following is an example of setting up an input file callback for |
|
* fetching compiled-in resources from @ref Corrade::Utility::Resource. |
|
* See the overload below for a more convenient type-safe way to pass |
|
* the user data pointer. |
|
* |
|
* @snippet ShaderTools.cpp AbstractConverter-setInputFileCallback |
|
* |
|
* @see @ref ShaderTools-AbstractConverter-usage-callbacks |
|
*/ |
|
/** @todo once porting away from std::string, it might make sense to |
|
also return a const void view (so it's always implicitly |
|
convertible) and not an Optional (as in, empty but non-null view |
|
would be used for empty files and null would be a failure); then it |
|
also might make sense to have fileCallback() return a char view |
|
again to avoid ugly casts in all user code */ |
|
void setInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* userData = nullptr); |
|
|
|
/** |
|
* @brief Set file opening callback |
|
* |
|
* Equivalent to calling the above with a lambda wrapper that casts |
|
* @cpp void* @ce back to @cpp T* @ce and dereferences it in order to |
|
* pass it to @p callback. Example usage --- this reuses an existing |
|
* @ref Corrade::Utility::Resource instance to avoid a potentially slow |
|
* resource group lookup every time: |
|
* |
|
* @snippet ShaderTools.cpp AbstractConverter-setInputFileCallback-template |
|
* |
|
* @see @ref ShaderTools-AbstractConverter-usage-callbacks |
|
*/ |
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
template<class T> void setInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, T&), T& userData); |
|
#else |
|
/* Otherwise the user would be forced to use the + operator to convert |
|
a lambda to a function pointer and (besides being weird and |
|
annoying) it's also not portable because it doesn't work on MSVC |
|
2015 and older versions of MSVC 2017. */ |
|
template<class Callback, class T> void setInputFileCallback(Callback callback, T& userData); |
|
#endif |
|
|
|
/** |
|
* @brief Set input format version |
|
* |
|
* @ref Format::Unspecified and an empty version is always accepted, |
|
* other values are interpreted in a plugin-specific way. If a |
|
* format/version combination is not supported or recognized, the |
|
* following @ref validateData(), @ref validateFile(), |
|
* @ref convertDataToData(), @ref convertDataToFile(), |
|
* @ref convertFileToFile(), @ref convertFileToData(), |
|
* @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() |
|
* or @ref linkFilesToData() call will fail. |
|
* |
|
* The @p format parameter corresponds to the `--input-format` option |
|
* in @ref magnum-shaderconverter "magnum-shaderconverter", |
|
* @p version to `--input-version`. |
|
* @see @ref setOutputFormat() |
|
*/ |
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
void setInputFormat(Format format, Containers::StringView version = {}); |
|
#else /* To avoid including StringView */ |
|
void setInputFormat(Format format, Containers::StringView version); |
|
void setInputFormat(Format format); |
|
#endif |
|
|
|
/** |
|
* @brief Set output format version |
|
* |
|
* @ref Format::Unspecified and an empty version is always accepted, |
|
* other values are interpreted in a plugin-specific way. If a |
|
* format/version combination is not supported or recognized, the |
|
* following @ref validateData(), @ref validateFile(), |
|
* @ref convertDataToData(), @ref convertDataToFile(), |
|
* @ref convertFileToFile(), @ref convertFileToData(), |
|
* @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() |
|
* or @ref linkFilesToData() call will fail. |
|
* |
|
* The @p format parameter corresponds to the `--output-format` option |
|
* in @ref magnum-shaderconverter "magnum-shaderconverter", |
|
* @p version to `--output-version`. |
|
* @see @ref setInputFormat() |
|
*/ |
|
#ifdef DOXYGEN_GENERATING_OUTPUT |
|
void setOutputFormat(Format format, Containers::StringView version = {}); |
|
#else /* To avoid including StringView */ |
|
void setOutputFormat(Format format, Containers::StringView version); |
|
void setOutputFormat(Format format); |
|
#endif |
|
|
|
/** |
|
* @brief Set preprocessor definitions |
|
* |
|
* Available only if @ref ConverterFeature::Preprocess is supported. |
|
* First string is macro name, second its value. If the second string |
|
* is empty (but not @cpp nullptr @ce), it's the same as |
|
* @cpp #define @ce without a value; if the second string is |
|
* @cpp nullptr @ce, it's the same as @cpp #undef @ce. |
|
* |
|
* Calling this function replaces the previous set, calling it with an |
|
* empty list will reset the definitions back to initial state. |
|
* |
|
* Corresponds to the `-D` / `--define` and `-U` / `--undefine` options |
|
* in @ref magnum-shaderconverter "magnum-shaderconverter". |
|
* @see @ref ConverterFlag::PreprocessOnly |
|
*/ |
|
void setDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions); |
|
|
|
/** @overload */ |
|
void setDefinitions(std::initializer_list<Containers::Pair<Containers::StringView, Containers::StringView>> definitions); |
|
|
|
/** |
|
* @brief Set optimization level |
|
* |
|
* Available only if @ref ConverterFeature::Optimize is supported. |
|
* Interpreted in a plugin-specific way, if it's not recognized the |
|
* following @ref convertDataToData(), @ref convertDataToFile(), |
|
* @ref convertFileToFile(), @ref convertFileToData(), |
|
* @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() |
|
* or @ref linkFilesToData() call will fail. |
|
* |
|
* Has no effect for @ref validateData() or @ref validateFile(). |
|
* |
|
* Corresponds to the `-O` / `--optimize` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
* @see @ref setDebugInfoLevel() |
|
*/ |
|
void setOptimizationLevel(Containers::StringView level); |
|
|
|
/** |
|
* @brief Set debug info level |
|
* |
|
* Available only if @ref ConverterFeature::DebugInfo is supported. |
|
* Interpreted in a plugin-specific way, if it's not recognized the |
|
* following @ref convertDataToData(), @ref convertDataToFile(), |
|
* @ref convertFileToFile(), @ref convertFileToData(), |
|
* @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() |
|
* or @ref linkFilesToData() call will fail. |
|
* |
|
* Has no effect for @ref validateData() or @ref validateFile(). |
|
* |
|
* Corresponds to the `-g` / `--debug-info` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
* @see @ref setOptimizationLevel() |
|
*/ |
|
void setDebugInfoLevel(Containers::StringView level); |
|
|
|
/** |
|
* @brief Validate a shader |
|
* |
|
* Available only if @ref ConverterFeature::ValidateData is |
|
* supported. Returns |
|
* |
|
* - @cpp true @ce and an empty string if validation passes without |
|
* warnings, |
|
* - @cpp true @ce and a non-empty string if validation passes with |
|
* warnings, and |
|
* - @cpp false @ce if validation doesn't pass. If an external error |
|
* occurs (for example a referenced file not being found), it may |
|
* also happen that the returned string is empty and a message is |
|
* printed to @relativeref{Magnum,Error} instead. |
|
* |
|
* @see @ref features(), @ref validateFile() |
|
*/ |
|
Containers::Pair<bool, Containers::String> validateData(Stage stage, Containers::ArrayView<const void> data); |
|
|
|
/** |
|
* @brief Validate a shader |
|
* |
|
* Available only if @ref ConverterFeature::ValidateFile or |
|
* @ref ConverterFeature::ValidateData is supported. Returns |
|
* |
|
* - @cpp true @ce and an empty string if validation passes without |
|
* warnings, |
|
* - @cpp true @ce and a non-empty string if validation passes with |
|
* warnings, and |
|
* - @cpp false @ce if validation doesn't pass. If an external error |
|
* occurs (for example when a file cannot be read), it may also |
|
* happen that the returned string is empty and a message is |
|
* printed to @relativeref{Magnum,Error} instead. |
|
* |
|
* Corresponds to the `--validate` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
* @see @ref features(), @ref validateData() |
|
*/ |
|
Containers::Pair<bool, Containers::String> validateFile(Stage stage, Containers::StringView filename); |
|
|
|
/** |
|
* @brief Convert shader data to a data |
|
* |
|
* Available only if @ref ConverterFeature::ConvertData is supported. |
|
* On failure prints a message to @relativeref{Magnum,Error} and |
|
* returns @cpp nullptr @ce. |
|
* @see @ref features(), @ref convertDataToFile(), |
|
* @ref convertFileToData(), @ref convertFileToFile() |
|
*/ |
|
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
Containers::Optional<Containers::Array<char>> |
|
#else |
|
Implementation::OptionalButAlsoArray<char> |
|
#endif |
|
convertDataToData(Stage stage, Containers::ArrayView<const void> data); |
|
|
|
/** |
|
* @brief Convert shader data to a file |
|
* |
|
* Available only if @ref ConverterFeature::ConvertData is supported. |
|
* On failure prints a message to @relativeref{Magnum,Error} and |
|
* returns @cpp false @ce. |
|
* @see @ref features(), @ref convertDataToData(), |
|
* @ref convertFileToData(), @ref convertFileToFile() |
|
*/ |
|
bool convertDataToFile(Stage stage, Containers::ArrayView<const void> data, Containers::StringView filename); |
|
|
|
/** |
|
* @brief Convert shader file to a file |
|
* |
|
* Available only if @ref ConverterFeature::ConvertFile or |
|
* @ref ConverterFeature::ConvertData is supported. On failure prints a |
|
* message to @relativeref{Magnum,Error} and returns @cpp false @ce. |
|
* |
|
* Corresponds to the default behavior of |
|
* @ref magnum-shaderconverter "magnum-shaderconverter" when neither |
|
* `--validate` nor `--link` is specified. |
|
* @see @ref features(), @ref convertFileToData(), |
|
* @ref convertDataToData(), @ref convertDataToFile() |
|
*/ |
|
bool convertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to); |
|
|
|
/** |
|
* @brief Convert shader data to a file |
|
* |
|
* Available only if @ref ConverterFeature::ConvertData is supported. |
|
* On failure prints a message to @relativeref{Magnum,Error} and |
|
* returns @relativeref{Corrade,Containers::NullOpt}. |
|
* @see @ref features(), @ref convertFileToFile(), |
|
* @ref convertDataToFile(), @ref convertDataToData() |
|
*/ |
|
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
Containers::Optional<Containers::Array<char>> |
|
#else |
|
Implementation::OptionalButAlsoArray<char> |
|
#endif |
|
convertFileToData(Stage stage, Containers::StringView filename); |
|
|
|
/** |
|
* @brief Link shader data together to a data |
|
* |
|
* Available only if @ref ConverterFeature::LinkData is supported. On |
|
* failure prints a message to @relativeref{Magnum,Error} and returns |
|
* @relativeref{Corrade,Containers::NullOpt}. Can't be called if |
|
* @ref ConverterFlag::PreprocessOnly is set --- in that case |
|
* @ref convertDataToData() has to be used instead. |
|
* @see @ref features() @ref linkDataToFile(), @ref linkFilesToFile() |
|
*/ |
|
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
Containers::Optional<Containers::Array<char>> |
|
#else |
|
Implementation::OptionalButAlsoArray<char> |
|
#endif |
|
linkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data); |
|
|
|
/** @overload */ |
|
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
Containers::Optional<Containers::Array<char>> |
|
#else |
|
Implementation::OptionalButAlsoArray<char> |
|
#endif |
|
linkDataToData(std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data); |
|
|
|
/** |
|
* @brief Link shader data together to a file |
|
* |
|
* Available only if @ref ConverterFeature::LinkData is supported. On |
|
* failure prints a message to @relativeref{Magnum,Error} and returns |
|
* @cpp false @ce. Can't be called if |
|
* @ref ConverterFlag::PreprocessOnly is set --- in that case |
|
* @ref convertDataToFile() has to be used instead. |
|
* @see @ref features(), @ref linkFilesToFile(), |
|
* @ref linkFilesToData(), @ref linkDataToData() |
|
*/ |
|
bool linkDataToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename); |
|
|
|
/** @overload */ |
|
bool linkDataToFile(std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename); |
|
|
|
/** |
|
* @brief Link shader files together to a file |
|
* |
|
* Available only if @ref ConverterFeature::LinkFile or |
|
* @ref ConverterFeature::LinkData is supported. On failure prints a |
|
* message to @relativeref{Magnum,Error} and returns @cpp false @ce. |
|
* Can't be called if @ref ConverterFlag::PreprocessOnly is set --- in |
|
* that case @ref convertFileToFile() has to be used instead. |
|
* |
|
* Corresponds to the `--link` option in |
|
* @ref magnum-shaderconverter "magnum-shaderconverter". |
|
* @see @ref features(), @ref linkFilesToData(), @ref linkDataToFile(), |
|
* @ref linkDataToData() |
|
*/ |
|
bool linkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to); |
|
|
|
/** @overload */ |
|
bool linkFilesToFile(std::initializer_list<Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to); |
|
|
|
/** |
|
* @brief Link shader files together to a data |
|
* |
|
* Available only if @ref ConverterFeature::LinkData is supported. On |
|
* failure prints a message to @relativeref{Magnum,Error} and returns |
|
* @relativeref{Corrade,Containers::NullOpt}. Can't be called if |
|
* @ref ConverterFlag::PreprocessOnly is set --- in that case |
|
* @ref convertFileToData() has to be used instead. |
|
* @see @ref features(), @ref linkFilesToFile(), @ref linkDataToFile(), |
|
* @ref linkDataToData() |
|
*/ |
|
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
Containers::Optional<Containers::Array<char>> |
|
#else |
|
Implementation::OptionalButAlsoArray<char> |
|
#endif |
|
linkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames); |
|
|
|
/** @overload */ |
|
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT) |
|
Containers::Optional<Containers::Array<char>> |
|
#else |
|
Implementation::OptionalButAlsoArray<char> |
|
#endif |
|
linkFilesToData(std::initializer_list<Containers::Pair<Stage, Containers::StringView>> filenames); |
|
|
|
protected: |
|
/** |
|
* @brief Implementation for @ref validateFile() |
|
* |
|
* If @ref ConverterFeature::ValidateData is supported, default |
|
* implementation opens the file and calls @ref doValidateData() with |
|
* its contents. It is allowed to call this function from your |
|
* @ref doValidateFile() implementation --- in particular, this |
|
* implementation will also correctly handle callbacks set through |
|
* @ref setInputFileCallback(). |
|
* |
|
* This function is not called when file callbacks are set through |
|
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback |
|
* is not supported --- instead, file is loaded though the callback and |
|
* data passed through to @ref doValidateData(). |
|
*/ |
|
virtual Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename); |
|
|
|
/** |
|
* @brief Implementation for @ref convertFileToFile() |
|
* |
|
* If @ref ConverterFeature::ConvertData is supported, default |
|
* implementation opens the file and calls @ref doConvertDataToData() |
|
* with its contents, then saving the output to a file. It is allowed |
|
* to call this function from your @ref doConvertFileToFile() |
|
* implementation --- in particular, this implementation will also |
|
* correctly handle callbacks set through @ref setInputFileCallback(). |
|
* |
|
* This function is not called when file callbacks are set through |
|
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback |
|
* is not supported --- instead, file is loaded though the callback and |
|
* data passed through to @ref doConvertDataToData(). |
|
*/ |
|
virtual bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to); |
|
|
|
/** |
|
* @brief Implementation for @ref convertFileToData() |
|
* |
|
* Default implementation opens the file and calls |
|
* @ref doConvertDataToData() with its contents --- you only need to |
|
* implement this if you need to do extra work with file inputs. It is |
|
* allowed to call this function from your @ref doConvertFileToData() |
|
* implementation --- in particular, this implementation will also |
|
* correctly handle callbacks set through @ref setInputFileCallback(). |
|
* |
|
* This function is not called when file callbacks are set through |
|
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback |
|
* is not supported --- instead, file is loaded though the callback and |
|
* data passed through to @ref doConvertDataToData(). |
|
*/ |
|
virtual Containers::Optional<Containers::Array<char>> doConvertFileToData(Stage stage, Containers::StringView filename); |
|
|
|
/** |
|
* @brief Implementation for @ref linkFilesToFile() |
|
* |
|
* If @ref ConverterFeature::LinkData is supported, default |
|
* implementation opens all files and calls @ref linkDataToData() with |
|
* their contents It is allowed to call this function from your |
|
* @ref doLinkFilesToFile() implementation --- in particular, this |
|
* implementation will also correctly handle callbacks set through |
|
* @ref setInputFileCallback(). |
|
* |
|
* This function is not called when file callbacks are set through |
|
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback |
|
* is not supported --- instead, file is loaded though the callback and |
|
* data passed through to @ref doLinkDataToData(). |
|
*/ |
|
virtual bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to); |
|
|
|
/** |
|
* @brief Implementation for @ref linkFilesToData() |
|
* |
|
* Default implementation opens all files and calls |
|
* @ref doLinkDataToData() with their contents --- you only need to |
|
* implement this if you need to do extra work with file inputs. It is |
|
* allowed to call this function from your @ref doLinkFilesToData() |
|
* implementation --- in particular, this implementation will also |
|
* correctly handle callbacks set through @ref setInputFileCallback(). |
|
* |
|
* This function is not called when file callbacks are set through |
|
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback |
|
* is not supported --- instead, file is loaded though the callback and |
|
* data passed through to @ref doConvertDataToData(). |
|
*/ |
|
virtual Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames); |
|
|
|
private: |
|
/** |
|
* @brief Implementation for @ref features() |
|
* |
|
* Has to be implemented always, the implementation is expected to |
|
* support at least one feature. |
|
*/ |
|
virtual ConverterFeatures doFeatures() const = 0; |
|
|
|
/** |
|
* @brief Implementation for @ref setFlags() |
|
* |
|
* Useful when the converter needs to modify some internal state on |
|
* flag setup. Default implementation does nothing and this |
|
* function doesn't need to be implemented --- the flags are available |
|
* through @ref flags(). |
|
* |
|
* To reduce the amount of error checking on user side, this function |
|
* isn't expected to fail --- if a flag combination is invalid / |
|
* unsuported, error reporting should be delayed to various conversion |
|
* functions, where the user is expected to do error handling anyway. |
|
*/ |
|
virtual void doSetFlags(ConverterFlags flags); |
|
|
|
/** |
|
* @brief Implementation for @ref setInputFileCallback() |
|
* |
|
* Useful when the converter needs to modify some internal state on |
|
* callback setup. Default implementation does nothing and this |
|
* function doesn't need to be implemented --- the callback function |
|
* and user data pointer are available through @ref inputFileCallback() |
|
* and @ref inputFileCallbackUserData(). |
|
*/ |
|
virtual void doSetInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* userData); |
|
|
|
/** |
|
* @brief Implementation for @ref setInputFormat() |
|
* |
|
* Has to be implemented always. To simplify error handling on user |
|
* side, this function isn't expected to fail --- if the format/version |
|
* combination isn't recognized, the following @ref validateData(), |
|
* @ref validateFile(), @ref convertDataToData(), |
|
* @ref convertDataToFile(), @ref convertFileToFile(), |
|
* @ref convertFileToData(), @ref linkDataToData(), |
|
* @ref linkDataToFile(), @ref linkFilesToFile() or |
|
* @ref linkFilesToData() should fail instead. |
|
*/ |
|
virtual void doSetInputFormat(Format format, Containers::StringView version) = 0; |
|
|
|
/** |
|
* @brief Implementation for @ref setOutputFormat() |
|
* |
|
* Has to be implemented always. To simplify error handling on user |
|
* side, this function isn't expected to fail --- if the format/version |
|
* combination isn't recognized, the following @ref validateData(), |
|
* @ref validateFile(), @ref convertDataToData(), |
|
* @ref convertDataToFile(), @ref convertFileToFile(), |
|
* @ref convertFileToData(), @ref linkDataToData(), |
|
* @ref linkDataToFile(), @ref linkFilesToFile() or |
|
* @ref linkFilesToData() should fail instead. |
|
*/ |
|
virtual void doSetOutputFormat(Format format, Containers::StringView version) = 0; |
|
|
|
/** |
|
* @brief Implementation for @ref setDefinitions() |
|
* |
|
* Has to be implemented if @ref ConverterFeature::Preprocess is |
|
* supported. This function isn't expected to fail. |
|
*/ |
|
virtual void doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions); |
|
|
|
/** |
|
* @brief Implementation for @ref setOptimizationLevel() |
|
* |
|
* Has to be implemented if @ref ConverterFeature::Optimize is |
|
* supported. To simplify error handling on user side, this function |
|
* isn't expected to fail --- if the level isn't recognized, the |
|
* following @ref convertDataToData(), @ref convertDataToFile(), |
|
* @ref convertFileToFile(), @ref convertFileToData(), |
|
* @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() |
|
* or @ref linkFilesToData() should fail instead. |
|
*/ |
|
virtual void doSetOptimizationLevel(Containers::StringView level); |
|
|
|
/** |
|
* @brief Implementation for @ref setDebugInfoLevel() |
|
* |
|
* Has to be implemented if @ref ConverterFeature::DebugInfo is |
|
* supported. To simplify error handling on user side, this function |
|
* isn't expected to fail --- if the level isn't recognized, the |
|
* following @ref convertDataToData(), @ref convertDataToFile(), |
|
* @ref convertFileToFile(), @ref convertFileToData(), |
|
* @ref linkDataToData(), @ref linkDataToFile(), @ref linkFilesToFile() |
|
* or @ref linkFilesToData() should fail instead. |
|
*/ |
|
virtual void doSetDebugInfoLevel(Containers::StringView level); |
|
|
|
/** |
|
* @brief Implementation for @ref validateData() |
|
* |
|
* Has to be implemented if @ref ConverterFeature::ValidateData |
|
* is supported. While @ref validateData() uses a @cpp void @ce view in |
|
* order to accept any type, this function gets it cast to |
|
* @cpp char @ce for more convenience. |
|
*/ |
|
virtual Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data); |
|
|
|
/* Used by convertFileToFile(), doConvertFileToFile(), |
|
convertFileToData() and doConvertFileToData() */ |
|
MAGNUM_SHADERTOOLS_LOCAL Containers::Optional<Containers::Array<char>> convertDataToDataUsingInputFileCallbacks(const char* prefix, const Stage stage, Containers::StringView filename); |
|
|
|
/** |
|
* @brief Implementation for @ref convertDataToData() |
|
* |
|
* Has to be implemented if @ref ConverterFeature::ConvertData is |
|
* supported. While @ref convertDataToData() uses a @cpp void @ce view |
|
* in order to accept any type, this function gets it cast to |
|
* @cpp char @ce for more convenience. |
|
*/ |
|
virtual Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage stage, Containers::ArrayView<const char> data); |
|
|
|
/* Used by linkFilesToFile(), doLinkFilesToFile(), linkFilesToData() |
|
and doLinkFilesToData() */ |
|
MAGNUM_SHADERTOOLS_LOCAL Containers::Optional<Containers::Array<char>> linkDataToDataUsingInputFileCallbacks(const char* prefix, Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames); |
|
|
|
/** |
|
* @brief Implementation for @ref linkDataToData() |
|
* |
|
* Has to be implemented if @ref ConverterFeature::LinkData is |
|
* supported. While @ref linkDataToData() uses a @cpp void @ce view in |
|
* order to accept any type, this function gets it cast to |
|
* @cpp char @ce for more convenience. |
|
*/ |
|
virtual Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data); |
|
|
|
ConverterFlags _flags; |
|
|
|
Containers::Optional<Containers::ArrayView<const char>>(*_inputFileCallback)(const std::string&, InputFileCallbackPolicy, void*){}; |
|
void* _inputFileCallbackUserData{}; |
|
|
|
/* Used by the templated version only */ |
|
struct FileCallbackTemplate { |
|
void(*callback)(); |
|
const void* userData; |
|
/* GCC 4.8 complains loudly about missing initializers otherwise */ |
|
} _inputFileCallbackTemplate{nullptr, nullptr}; |
|
}; |
|
|
|
/** |
|
@brief Shader converter plugin interface |
|
@m_since_latest |
|
|
|
Same string as returned by |
|
@relativeref{Magnum::ShaderTools,AbstractConverter::pluginInterface()}, meant |
|
to be used inside @ref CORRADE_PLUGIN_REGISTER() to avoid having to update the |
|
interface string by hand every time the version gets bumped: |
|
|
|
@snippet ShaderTools.cpp MAGNUM_SHADERTOOLS_ABSTRACTCONVERTER_PLUGIN_INTERFACE |
|
|
|
The interface string version gets increased on every ABI break to prevent |
|
silent crashes and memory corruption. Plugins built against the previous |
|
version will then fail to load, a subsequent rebuild will make them pick up the |
|
updated interface string. |
|
*/ |
|
/* Silly indentation to make the string appear in pluginInterface() docs */ |
|
#define MAGNUM_SHADERTOOLS_ABSTRACTCONVERTER_PLUGIN_INTERFACE /* [interface] */ \ |
|
"cz.mosra.magnum.ShaderTools.AbstractConverter/0.1.1" |
|
/* [interface] */ |
|
|
|
#ifndef DOXYGEN_GENERATING_OUTPUT |
|
template<class Callback, class T> void AbstractConverter::setInputFileCallback(Callback callback, T& userData) { |
|
/* Don't try to wrap a null function pointer. Need to cast first because |
|
MSVC (even 2017) can't apply ! to a lambda. Ugh. */ |
|
const auto callbackPtr = static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&)>(callback); |
|
/* With -std=c++17 or higher enabled, GCC says that "warning: the address |
|
of <a lambda> will never be NULL". Well of course it won't, but this |
|
function can get also a null plain function pointer, it's a goddamn |
|
template after all. Shut up. */ |
|
#if defined(CORRADE_TARGET_GCC) && !defined(CORRADE_TARGET_CLANG) && defined(CORRADE_TARGET_CXX17) |
|
#pragma GCC diagnostic push |
|
#pragma GCC diagnostic ignored "-Waddress" |
|
#endif |
|
if(!callbackPtr) |
|
return setInputFileCallback(nullptr); |
|
#if defined(CORRADE_TARGET_GCC) && !defined(CORRADE_TARGET_CLANG) && defined(CORRADE_TARGET_CXX17) |
|
#pragma GCC diagnostic pop |
|
#endif |
|
|
|
_inputFileCallbackTemplate = { reinterpret_cast<void(*)()>(callbackPtr), static_cast<const void*>(&userData) }; |
|
setInputFileCallback([](const std::string& filename, const InputFileCallbackPolicy flags, void* const userData) { |
|
auto& s = *reinterpret_cast<FileCallbackTemplate*>(userData); |
|
return reinterpret_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&)>(s.callback)(filename, flags, *static_cast<T*>(const_cast<void*>(s.userData))); |
|
}, &_inputFileCallbackTemplate); |
|
} |
|
#endif |
|
|
|
}} |
|
|
|
#endif
|
|
|