Browse Source

ShaderTools: add a linking API to AbstractConverter.

Eh. Am I overdoing it with the tests?
pull/481/head
Vladimír Vondruš 6 years ago
parent
commit
332030aaa2
  1. 243
      src/Magnum/ShaderTools/AbstractConverter.cpp
  2. 219
      src/Magnum/ShaderTools/AbstractConverter.h
  3. 1803
      src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp
  4. 2
      src/Magnum/ShaderTools/Test/CMakeLists.txt
  5. 1
      src/Magnum/ShaderTools/Test/another.dat

243
src/Magnum/ShaderTools/AbstractConverter.cpp

@ -94,7 +94,7 @@ void AbstractConverter::setInputFileCallback(Containers::Optional<Containers::Ar
/* Clearing the *File bits as those are present in *Data as well and thus
this would pass even if only file conversion/validation is supported,
which is wrong */
CORRADE_ASSERT(features() & (ConverterFeature::InputFileCallback|ConverterFeature::ValidateData|ConverterFeature::ConvertData) & ~(ConverterFeature::ValidateFile|ConverterFeature::ConvertFile),
CORRADE_ASSERT(features() & (ConverterFeature::InputFileCallback|ConverterFeature::ValidateData|ConverterFeature::ConvertData|ConverterFeature::LinkData) & ~(ConverterFeature::ValidateFile|ConverterFeature::ConvertFile|ConverterFeature::LinkFile),
"ShaderTools::AbstractConverter::setInputFileCallback(): converter supports neither loading from data nor via callbacks, callbacks can't be used", );
_inputFileCallback = callback;
@ -350,6 +350,242 @@ Containers::Array<char> AbstractConverter::doConvertFileToData(const Stage stage
}
}
Containers::Array<char> AbstractConverter::linkDataToData(const Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkDataToData(): feature not supported", {});
CORRADE_ASSERT(!data.empty(),
"ShaderTools::AbstractConverter::linkDataToData(): no data passed", {});
/* Cast to a non-void type for more convenience */
Containers::Array<char> out = doLinkDataToData(Containers::arrayCast<const std::pair<Stage, Containers::ArrayView<const char>>>(data));
CORRADE_ASSERT(!out.deleter(),
"ShaderTools::AbstractConverter::linkDataToData(): implementation is not allowed to use a custom Array deleter", {});
return out;
}
Containers::Array<char> AbstractConverter::linkDataToData(const std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data) {
return linkDataToData(Containers::arrayView(data));
}
Containers::Array<char> AbstractConverter::doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented", {});
}
bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView to) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkDataToFile(): feature not supported", {});
CORRADE_ASSERT(!data.empty(),
"ShaderTools::AbstractConverter::linkDataToFile(): no data passed", {});
/** @todo this needs expansion once output callbacks are supported as well */
/* Cast to a non-void type for more convenience */
Containers::Array<char> out = doLinkDataToData(Containers::arrayCast<const std::pair<Stage, Containers::ArrayView<const char>>>(data));
if(!out) return false;
if(!Utility::Directory::write(to, out)) {
Error{} << "ShaderTools::AbstractConverter::linkDataToFile(): cannot write to file" << to;
return false;
}
return true;
}
bool AbstractConverter::linkDataToFile(const std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView to) {
return linkDataToFile(Containers::arrayView(data), to);
}
Containers::Array<char> AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) {
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{Containers::NoInit, from.size()};
/* First load all files. Remember how many of these succeeded so we can
close them again after */
std::size_t i;
for(i = 0; i != from.size(); ++i) {
const Containers::Optional<Containers::ArrayView<const char>> contents = _inputFileCallback(from[i].second, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData);
if(!contents) break;
data[i].first = from[i].first;
data[i].second = *contents;
}
/* If all input files loaded successfully, process */
Containers::Array<char> out;
if(i == from.size()) out = doLinkDataToData(data);
/* Close again all input files that loaded successfully */
for(std::size_t ii = 0; ii != i; ++ii)
_inputFileCallback(from[ii].second, InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
/* Now that we have cleaned up correctly, it's time print the error message
if something didn't go well. IN this case doLinkDataToData() was not
called at all. */
if(i != from.size()) {
Error{} << prefix << "cannot open file" << from[i].second;
return {};
}
/* Return the data. This could have failed too, but the error message got
printed by the implementation already */
return out;
}
bool AbstractConverter::linkFilesToFile(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
CORRADE_ASSERT(features() & (ConverterFeature::LinkFile|ConverterFeature::LinkData),
"ShaderTools::AbstractConverter::linkFilesToFile(): feature not supported", {});
CORRADE_ASSERT(!from.empty(),
"ShaderTools::AbstractConverter::linkFilesToFile(): no files passed", {});
/** @todo this needs expansion once output callbacks are supported as well */
/* If input file callbacks are not set or the converter supports handling
them directly, call into the implementation */
if(!_inputFileCallback || (doFeatures() & ConverterFeature::InputFileCallback)) {
return doLinkFilesToFile(from, to);
/* Otherwise, if converting data is supported, use the callback and pass
the data through to convertDataToData(). Mark the file as ready to be
closed once conversion is finished. */
} else if(doFeatures() & ConverterFeature::LinkData) {
/* This needs to be duplicated here and in the doLinkFilesToFile()
implementation in order to support both following cases:
- plugins that don't support InputFileCallback but have their own
doLinkFilesToFile() implementation (callback needs to be used
here, because the base doLinkFilesToFile() implementation might
never get called)
- plugins that support InputFileCallback but want to delegate the
actual file loading to the default implementation (callback used
in the base doLinkFilesToFile() implementation, because this
branch is never taken in that case) */
Containers::Array<char> out = linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToFile():", from);
if(!out) return false;
if(!Utility::Directory::write(to, out)) {
Error{} << "ShaderTools::AbstractConverter::linkFilesToFile(): cannot write to file" << to;
return false;
}
return true;
/* Shouldn't get here, the assert is fired already in setFileCallback() */
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
bool AbstractConverter::linkFilesToFile(const std::initializer_list<std::pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
return linkFilesToFile(Containers::arrayView(from), to);
}
bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData, "ShaderTools::AbstractConverter::linkFilesToFile(): feature advertised but not implemented", {});
/** @todo this needs expansion once output callbacks are supported as well */
Containers::Array<char> out;
/* If callbacks are set, use them. This is the same implementation as in
convertFileToFile(), see the comment there for details. */
if(_inputFileCallback) {
out = linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToFile():", from);
/* Otherwise open the files directly */
} else {
Containers::Array<Containers::Array<char>> fileData{from.size()};
for(std::size_t i = 0; i != from.size(); ++i) {
if(!Utility::Directory::exists(from[i].second)) {
Error() << "ShaderTools::AbstractConverter::linkFilesToFile(): cannot open file" << from[i].second;
return {};
}
fileData[i] = Utility::Directory::read(from[i].second);
}
/** @todo merge the allocations once we have an ArrayTuple */
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{Containers::NoInit, from.size()};
for(std::size_t i = 0; i != from.size(); ++i) {
data[i].first = from[i].first;
data[i].second = fileData[i];
}
out = doLinkDataToData(data);
}
if(!out) return false;
if(!Utility::Directory::write(to, out)) {
Error{} << "ShaderTools::AbstractConverter::linkFilesToFile(): cannot write to file" << to;
return false;
}
return true;
}
Containers::Array<char> AbstractConverter::linkFilesToData(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkFilesToData(): feature not supported", {});
CORRADE_ASSERT(!from.empty(),
"ShaderTools::AbstractConverter::linkFilesToData(): no files passed", {});
Containers::Array<char> out;
/* If input file callbacks are not set or the converter supports handling
them directly, call into the implementation */
if(!_inputFileCallback || (doFeatures() & ConverterFeature::InputFileCallback)) {
out = doLinkFilesToData(from);
/* Otherwise use the callback and pass the data through to
convertDataToData(). Mark the file as ready to be closed once conversion
is finished. */
} else {
/* This needs to be duplicated here and in the doConvertFileToData()
implementation in order to support both following cases:
- plugins that don't support InputFileCallback but have their own
doLinkFilesToData() implementation (callback needs to be used
here, because the base doLinkFilesToData() implementation might
never get called)
- plugins that support InputFileCallback but want to delegate the
actual file loading to the default implementation (callback used
in the base doLinkFilesToData() implementation, because this
branch is never taken in that case) */
out = linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToData():", from);
}
CORRADE_ASSERT(!out.deleter(),
"ShaderTools::AbstractConverter::linkFilesToData(): implementation is not allowed to use a custom Array deleter", {});
return out;
}
Containers::Array<char> AbstractConverter::linkFilesToData(const std::initializer_list<std::pair<Stage, Containers::StringView>> from) {
return linkFilesToData(Containers::arrayView(from));
}
Containers::Array<char> AbstractConverter::doLinkFilesToData(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) {
/* If callbacks are set, use them. This is the same implementation as in
linkFilesToFile(), see the comment there for details. */
if(_inputFileCallback) {
return linkDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::linkFilesToData():", from);
/* Otherwise open the files directly */
} else {
Containers::Array<Containers::Array<char>> fileData{from.size()};
for(std::size_t i = 0; i != from.size(); ++i) {
if(!Utility::Directory::exists(from[i].second)) {
Error() << "ShaderTools::AbstractConverter::linkFilesToData(): cannot open file" << from[i].second;
return {};
}
fileData[i] = Utility::Directory::read(from[i].second);
}
/** @todo merge the allocations once we have an ArrayTuple */
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{Containers::NoInit, from.size()};
for(std::size_t i = 0; i != from.size(); ++i) {
data[i].first = from[i].first;
data[i].second = fileData[i];
}
return doLinkDataToData(data);
}
}
Debug& operator<<(Debug& debug, const ConverterFeature value) {
debug << "ShaderTools::ConverterFeature" << Debug::nospace;
@ -360,6 +596,8 @@ Debug& operator<<(Debug& debug, const ConverterFeature value) {
_c(ValidateFile)
_c(ConvertData)
_c(ConvertFile)
_c(LinkData)
_c(LinkFile)
_c(InputFileCallback)
#undef _c
/* LCOV_EXCL_STOP */
@ -376,6 +614,9 @@ Debug& operator<<(Debug& debug, const ConverterFeatures value) {
ConverterFeature::ConvertData,
/* Implied by ConvertData, has to be after */
ConverterFeature::ConvertFile,
ConverterFeature::LinkData,
/* Implied by LinkData, has to be after */
ConverterFeature::LinkFile,
ConverterFeature::InputFileCallback});
}

219
src/Magnum/ShaderTools/AbstractConverter.h

@ -70,6 +70,21 @@ enum class ConverterFeature: UnsignedInt {
*/
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
@ -79,7 +94,7 @@ enum class ConverterFeature: UnsignedInt {
* See @ref ShaderTools-AbstractConverter-usage-callbacks and particular
* converter documentation for more information.
*/
InputFileCallback = 1 << 4
InputFileCallback = 1 << 6
};
/**
@ -151,7 +166,9 @@ enum class Stage: UnsignedInt {
* Unspecified stage. When used in the
* @ref AbstractConverter::validateFile(),
* @ref AbstractConverter::convertFileToFile() "convertFileToFile()",
* @ref AbstractConverter::convertFileToData() "convertFileToData()" APIs,
* @ref AbstractConverter::convertFileToData() "convertFileToData()",
* @ref AbstractConverter::linkFilesToFile() "linkFilesToFile()" or
* @ref AbstractConverter::linkFilesToData() "linkFilesToData()" APIs,
* particular plugins may attempt to detect the stage from filename, the
* shader stage might also be encoded directly in certain formats. Leaving
* the stage unspecified might limit validation and conversion
@ -204,16 +221,17 @@ linking.
@subsection ShaderTools-AbstractConverter-usage-validation Shader validation
@subsection ShaderTools-AbstractConverter-usage-conversion Shader conversion
@subsection ShaderTools-AbstractConverter-usage-conversion Shader conversion and linking
@subsection ShaderTools-AbstractConverter-usage-callbacks Loading shaders from memory, using file callbacks
Besides loading shaders directly from the filesystem using @ref validateFile()
/ @ref convertFileToFile() like shown above, it's possible to use
@ref validateData(), @ref convertDataToData() and variants to load data from
memory. Note that the particular converter implementation has to support
@ref ConverterFeature::ValidateData / @ref ConverterFeature::ConvertData for
this method to work.
/ @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
@ -225,22 +243,25 @@ 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() as
well --- you don't have to load the top-level file manually and pass it to
@ref validateData() / @ref convertDataToData(), any converter supporting the
@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 MagnumShaderTools.cpp AbstractConverter-usage-callbacks
For converters that don't support @ref ConverterFeature::InputFileCallback
directly, the base @ref validateFile() / @ref convertFileToFile() /
@ref convertFileToData() implementations will use the file callback to pass
the loaded data through to @ref validateData() / @ref convertDataToData(), in
case the converter supports at least @ref ConverterFeature::ValidateData
/ @ref ConverterFeature::ConvertData. If the converter supports none of
@ref ConverterFeature::InputFileCallback, @ref ConverterFeature::ValidateData
or @ref ConverterFeature::ConvertData, @ref setInputFileCallback() doesn't
allow the callbacks to be set.
@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
@ -261,8 +282,9 @@ plugin module has been unloaded.
The plugin needs to implement the @ref doFeatures() function and one or more of
@ref doValidateData(), @ref doValidateFile(), @ref doConvertDataToData(),
@ref doConvertFileToData(), or @ref doConvertFileToFile() functions based on
what features are supported.
@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:
@ -275,6 +297,13 @@ checked by the implementation:
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}
@ -355,11 +384,12 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* @brief Set input file callback
*
* In case the converter supports @ref ConverterFeature::InputFileCallback,
* files opened through @ref validateFile(), @ref convertFileToData()
* and @ref convertFileToFile() 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,
* 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
@ -369,26 +399,31 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* In case the converter doesn't support
* @ref ConverterFeature::InputFileCallback but supports at least
* @ref ConverterFeature::ValidateData /
* @ref ConverterFeature::ConvertData, a file opened through
* @ref validateFile(), @ref convertFileToData() or
* @ref convertFileToFile() will be internally loaded through the
* provided callback and then passed to @ref validateData() or
* @ref convertDataToData(). 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() (sidestepping the potential
* @ref validateFile() / @ref convertFileToFile() 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() directly.
* @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. If a converter supports neither,
* callbacks can't be used.
* @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.
@ -507,6 +542,62 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
*/
Containers::Array<char> convertFileToData(Stage stage, const Containers::StringView from);
/**
* @brief Link shader data together to a data
*
* Available only if @ref ConverterFeature::LinkData is supported. On
* failure the function prints an error message and returns
* @cpp nullptr @ce.
* @see @ref features() @ref linkDataToFile(), @ref linkFilesToFile()
*/
Containers::Array<char> linkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data);
/** @overload */
Containers::Array<char> linkDataToData(std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data);
/**
* @brief Link shader data together to a file
*
* Available only if @ref ConverterFeature::LinkData is supported. On
* Returns @cpp true @ce on success, prints an error message and
* returns @cpp false @ce otherwise.
* @see @ref features(), @ref linkFilesToFile(),
* @ref linkFilesToData(), @ref linkDataToData()
*/
bool linkDataToFile(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView to);
/** @overload */
bool linkDataToFile(std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView to);
/**
* @brief Link shader files together to a file
*
* Available only if @ref ConverterFeature::LinkFile or
* @ref ConverterFeature::LinkData is supported. Returns @cpp true @ce
* on success, prints an error message and returns @cpp false @ce
* otherwise.
* @see @ref features(), @ref linkFilesToData(), @ref linkDataToFile(),
* @ref linkDataToData()
*/
bool linkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to);
/** @overload */
bool linkFilesToFile(std::initializer_list<std::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 the function prints an error message and returns
* @cpp nullptr @ce.
* @see @ref features(), @ref linkFilesToFile(), @ref linkDataToFile(),
* @ref linkDataToData()
*/
Containers::Array<char> linkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from);
/** @overload */
Containers::Array<char> linkFilesToData(std::initializer_list<std::pair<Stage, Containers::StringView>> from);
protected:
/**
* @brief Implementation for @ref validateFile()
@ -559,6 +650,40 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
*/
virtual Containers::Array<char> doConvertFileToData(Stage stage, Containers::StringView from);
/**
* @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 std::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::Array<char> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from);
private:
/**
* @brief Implementation for @ref features()
@ -618,6 +743,20 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
*/
virtual Containers::Array<char> doConvertDataToData(Stage stage, Containers::ArrayView<const char> data);
/* Used by linkFilesToFile(), doLinkFilesToFile(), linkFilesToData()
and doLinkFilesToData() */
MAGNUM_SHADERTOOLS_LOCAL Containers::Array<char> linkDataToDataUsingInputFileCallbacks(const char* prefix, Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from);
/**
* @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::Array<char> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data);
ConverterFlags _flags;
Containers::Optional<Containers::ArrayView<const char>>(*_inputFileCallback)(const std::string&, InputFileCallbackPolicy, void*){};

1803
src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp

File diff suppressed because it is too large Load Diff

2
src/Magnum/ShaderTools/Test/CMakeLists.txt

@ -36,6 +36,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake
corrade_add_test(ShaderToolsAbstractConverterTest AbstractConverterTest.cpp
LIBRARIES MagnumShaderToolsTestLib
FILES file.dat)
FILES file.dat another.dat)
target_include_directories(ShaderToolsAbstractConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

1
src/Magnum/ShaderTools/Test/another.dat

@ -0,0 +1 @@
VRIPS
Loading…
Cancel
Save