Browse Source

ShaderTools: port away from std::pair.

Here the benefit is especially clear -- as Containers::Pair is trivially
copyable with trivial types, all growable arrays can make use of
std::realloc() while with the STL variant a silly constructor, copy
constructor, destructor had to be used.

Additionally, we no longer need to take explicit care of libc++ and MSVC
STL where returning a std::pair<bool, Containers::String> as

    return {{}, Containers::String{..., <deleter>}};

would caused an unnecessary copy instead of a move, losing the custom
deleter in the process. Yay!

There's a <Corrade/Containers/PairStl.h> include for backwards
compatibility purposes, but obviously it would only work for the return
type of validate*() and cases where an initializer list was passed to a
list-of-pairs-taking functions, and not a concretely typed ArrayView.
Those functions were though mostly the linker API which isn't
implemented by any plugin yet, so it shouldn't be *that* breaking to
users. Neverteless, I'm trying to do this breaking change rather sooner
than later to prevent pain further down the road when the Vulkan APIs
and SPIR-V pipeline gets widely used.
pull/557/head
Vladimír Vondruš 4 years ago
parent
commit
7f4500d9e0
  1. 14
      doc/snippets/MagnumShaderTools.cpp
  2. 85
      src/Magnum/ShaderTools/AbstractConverter.cpp
  3. 45
      src/Magnum/ShaderTools/AbstractConverter.h
  4. 215
      src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp
  5. 17
      src/Magnum/ShaderTools/shaderconverter.cpp
  6. 24
      src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp
  7. 6
      src/MagnumPlugins/AnyShaderConverter/AnyConverter.h
  8. 49
      src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp

14
doc/snippets/MagnumShaderTools.cpp

@ -27,6 +27,7 @@
#include <unordered_map>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo drop when file callbacks are <string>-free */
#include <Corrade/Utility/Macros.h> /* CORRADE_LINE_STRING */
@ -47,14 +48,13 @@ PluginManager::Manager<ShaderTools::AbstractConverter> manager;
Containers::Pointer<ShaderTools::AbstractConverter> converter =
manager.loadAndInstantiate("AnyShaderConverter");
bool valid;
Containers::String message;
if(converter) std::tie(valid, message) =
Containers::Pair<bool, Containers::String> validMessage;
if(converter) validMessage =
converter->validateFile(ShaderTools::Stage::Unspecified, "file.spv");
if(!converter || !valid)
Error{} << "Validation failed:" << message;
else if(!message.isEmpty())
Warning{} << "Validation succeeded with warnings:" << message;
if(!converter || !validMessage.first())
Error{} << "Validation failed:" << validMessage.second();
else if(!validMessage.second().isEmpty())
Warning{} << "Validation succeeded with warnings:" << validMessage.second();
else
Debug{} << "Validation passed";
/* [AbstractConverter-usage-validation] */

85
src/Magnum/ShaderTools/AbstractConverter.cpp

@ -29,6 +29,7 @@
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once file callbacks are <string>-free */
#include <Corrade/PluginManager/Manager.hpp>
@ -151,17 +152,17 @@ void AbstractConverter::setOutputFormat(const Format format) {
return setOutputFormat(format, {});
}
void AbstractConverter::setDefinitions(const Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) {
void AbstractConverter::setDefinitions(const Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) {
CORRADE_ASSERT(features() & ConverterFeature::Preprocess,
"ShaderTools::AbstractConverter::setDefinitions(): feature not supported", );
doSetDefinitions(definitions);
}
void AbstractConverter::setDefinitions(std::initializer_list<std::pair<Containers::StringView, Containers::StringView>> definitions) {
void AbstractConverter::setDefinitions(std::initializer_list<Containers::Pair<Containers::StringView, Containers::StringView>> definitions) {
return setDefinitions(Containers::arrayView(definitions));
}
void AbstractConverter::doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>>) {
void AbstractConverter::doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>>) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::setDefinitions(): feature advertised but not implemented", );
}
@ -185,30 +186,30 @@ void AbstractConverter::doSetDebugInfoLevel(Containers::StringView) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::setDebugInfoLevel(): feature advertised but not implemented", );
}
std::pair<bool, Containers::String> AbstractConverter::validateData(const Stage stage, const Containers::ArrayView<const void> data) {
Containers::Pair<bool, Containers::String> AbstractConverter::validateData(const Stage stage, const Containers::ArrayView<const void> data) {
CORRADE_ASSERT(features() & ConverterFeature::ValidateData,
"ShaderTools::AbstractConverter::validateData(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
"ShaderTools::AbstractConverter::validateData(): PreprocessOnly is not allowed in combination with validation", {});
/* Cast to a non-void type for more convenience */
std::pair<bool, Containers::String> out = doValidateData(stage, Containers::arrayCast<const char>(data));
CORRADE_ASSERT(out.second.isSmall() || !out.second.deleter(),
Containers::Pair<bool, Containers::String> out = doValidateData(stage, Containers::arrayCast<const char>(data));
CORRADE_ASSERT(out.second().isSmall() || !out.second().deleter(),
"ShaderTools::AbstractConverter::validateData(): implementation is not allowed to use a custom String deleter", {});
return out;
}
std::pair<bool, Containers::String> AbstractConverter::doValidateData(Stage, Containers::ArrayView<const char>) {
Containers::Pair<bool, Containers::String> AbstractConverter::doValidateData(Stage, Containers::ArrayView<const char>) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::validateData(): feature advertised but not implemented", {});
}
std::pair<bool, Containers::String> AbstractConverter::validateFile(const Stage stage, const Containers::StringView filename) {
Containers::Pair<bool, Containers::String> AbstractConverter::validateFile(const Stage stage, const Containers::StringView filename) {
CORRADE_ASSERT(features() & (ConverterFeature::ValidateFile|ConverterFeature::ValidateData),
"ShaderTools::AbstractConverter::validateFile(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
"ShaderTools::AbstractConverter::validateFile(): PreprocessOnly is not allowed in combination with validation", {});
std::pair<bool, Containers::String> out;
Containers::Pair<bool, Containers::String> out;
/* If input file callbacks are not set or the converter supports handling
them directly, call into the implementation */
@ -240,12 +241,12 @@ std::pair<bool, Containers::String> AbstractConverter::validateFile(const Stage
/* Shouldn't get here, the assert is fired already in setFileCallback() */
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
CORRADE_ASSERT(out.second.isSmall() || !out.second.deleter(),
CORRADE_ASSERT(out.second().isSmall() || !out.second().deleter(),
"ShaderTools::AbstractConverter::validateFile(): implementation is not allowed to use a custom String deleter", {});
return out;
}
std::pair<bool, Containers::String> AbstractConverter::doValidateFile(const Stage stage, const Containers::StringView filename) {
Containers::Pair<bool, Containers::String> AbstractConverter::doValidateFile(const Stage stage, const Containers::StringView filename) {
CORRADE_ASSERT(features() >= ConverterFeature::ValidateData, "ShaderTools::AbstractConverter::validateFile(): feature advertised but not implemented", {});
/* If callbacks are set, use them. This is the same implementation as in
@ -256,7 +257,7 @@ std::pair<bool, Containers::String> AbstractConverter::doValidateFile(const Stag
Error{} << "ShaderTools::AbstractConverter::validateFile(): cannot open file" << filename;
return {};
}
std::pair<bool, Containers::String> out = doValidateData(stage, *data);
Containers::Pair<bool, Containers::String> out = doValidateData(stage, *data);
_inputFileCallback(filename, InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
return out;
@ -465,7 +466,7 @@ Containers::Optional<Containers::Array<char>>
#else
Implementation::OptionalButAlsoArray<char>
#endif
AbstractConverter::linkDataToData(const Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data) {
AbstractConverter::linkDataToData(const Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkDataToData(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -474,7 +475,7 @@ AbstractConverter::linkDataToData(const Containers::ArrayView<const std::pair<St
"ShaderTools::AbstractConverter::linkDataToData(): no data passed", {});
/* Cast to a non-void type for more convenience */
Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const std::pair<Stage, Containers::ArrayView<const char>>>(data));
Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const Containers::Pair<Stage, Containers::ArrayView<const char>>>(data));
CORRADE_ASSERT(!out || !out->deleter(),
"ShaderTools::AbstractConverter::linkDataToData(): implementation is not allowed to use a custom Array deleter", {});
@ -491,15 +492,15 @@ Containers::Optional<Containers::Array<char>>
#else
Implementation::OptionalButAlsoArray<char>
#endif
AbstractConverter::linkDataToData(const std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data) {
AbstractConverter::linkDataToData(const std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data) {
return linkDataToData(Containers::arrayView(data));
}
Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) {
Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkDataToData(Containers::ArrayView<const Containers::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 filename) {
bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView filename) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkDataToFile(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -510,7 +511,7 @@ bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const std::pa
/** @todo this needs expansion once output callbacks are supported as well */
/* Cast to a non-void type for more convenience */
const Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const std::pair<Stage, Containers::ArrayView<const char>>>(data));
const Containers::Optional<Containers::Array<char>> out = doLinkDataToData(Containers::arrayCast<const Containers::Pair<Stage, Containers::ArrayView<const char>>>(data));
if(!out) return false;
if(!Utility::Path::write(filename, *out)) {
@ -521,22 +522,22 @@ bool AbstractConverter::linkDataToFile(const Containers::ArrayView<const std::pa
return true;
}
bool AbstractConverter::linkDataToFile(const std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView filename) {
bool AbstractConverter::linkDataToFile(const std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data, const Containers::StringView filename) {
return linkDataToFile(Containers::arrayView(data), filename);
}
Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames) {
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.size()};
Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataUsingInputFileCallbacks(const char* const prefix, const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames) {
Containers::Array<Containers::Pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.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 != filenames.size(); ++i) {
const Containers::Optional<Containers::ArrayView<const char>> contents = _inputFileCallback(filenames[i].second, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData);
const Containers::Optional<Containers::ArrayView<const char>> contents = _inputFileCallback(filenames[i].second(), InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData);
if(!contents) break;
data[i].first = filenames[i].first;
data[i].second = *contents;
data[i].first() = filenames[i].first();
data[i].second() = *contents;
}
/* If all input files loaded successfully, process */
@ -545,13 +546,13 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataU
/* Close again all input files that loaded successfully */
for(std::size_t ii = 0; ii != i; ++ii)
_inputFileCallback(filenames[ii].second, InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
_inputFileCallback(filenames[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 != filenames.size()) {
Error{} << prefix << "cannot open file" << filenames[i].second;
Error{} << prefix << "cannot open file" << filenames[i].second();
return {};
}
@ -560,7 +561,7 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::linkDataToDataU
return out;
}
bool AbstractConverter::linkFilesToFile(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
bool AbstractConverter::linkFilesToFile(const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, const Containers::StringView to) {
CORRADE_ASSERT(features() & (ConverterFeature::LinkFile|ConverterFeature::LinkData),
"ShaderTools::AbstractConverter::linkFilesToFile(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -603,11 +604,11 @@ bool AbstractConverter::linkFilesToFile(const Containers::ArrayView<const std::p
} 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) {
bool AbstractConverter::linkFilesToFile(const std::initializer_list<Containers::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) {
bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const Containers::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 */
@ -622,9 +623,9 @@ bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const std:
} else {
Containers::Array<Containers::Array<char>> fileData{from.size()};
for(std::size_t i = 0; i != from.size(); ++i) {
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(from[i].second);
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(from[i].second());
if(!data) {
Error() << "ShaderTools::AbstractConverter::linkFilesToFile(): cannot open file" << from[i].second;
Error() << "ShaderTools::AbstractConverter::linkFilesToFile(): cannot open file" << from[i].second();
return {};
}
@ -633,10 +634,10 @@ bool AbstractConverter::doLinkFilesToFile(const Containers::ArrayView<const std:
/** @todo merge the allocations once we have an ArrayTuple (actually,
ideally it would merge also the nested allocations, how?) */
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{NoInit, from.size()};
Containers::Array<Containers::Pair<Stage, Containers::ArrayView<const char>>> data{NoInit, from.size()};
for(std::size_t i = 0; i != from.size(); ++i) {
data[i].first = from[i].first;
data[i].second = fileData[i];
data[i].first() = from[i].first();
data[i].second() = fileData[i];
}
out = doLinkDataToData(data);
@ -657,7 +658,7 @@ Containers::Optional<Containers::Array<char>>
#else
Implementation::OptionalButAlsoArray<char>
#endif
AbstractConverter::linkFilesToData(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames) {
AbstractConverter::linkFilesToData(const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames) {
CORRADE_ASSERT(features() >= ConverterFeature::LinkData,
"ShaderTools::AbstractConverter::linkFilesToData(): feature not supported", {});
CORRADE_ASSERT(!(_flags & ConverterFlag::PreprocessOnly),
@ -705,11 +706,11 @@ Containers::Optional<Containers::Array<char>>
#else
Implementation::OptionalButAlsoArray<char>
#endif
AbstractConverter::linkFilesToData(const std::initializer_list<std::pair<Stage, Containers::StringView>> filenames) {
AbstractConverter::linkFilesToData(const std::initializer_list<Containers::Pair<Stage, Containers::StringView>> filenames) {
return linkFilesToData(Containers::arrayView(filenames));
}
Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToData(const Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames) {
Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToData(const Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames) {
/* If callbacks are set, use them. This is the same implementation as in
linkFilesToFile(), see the comment there for details. */
if(_inputFileCallback) {
@ -719,9 +720,9 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToDa
} else {
Containers::Array<Containers::Array<char>> fileData{filenames.size()};
for(std::size_t i = 0; i != filenames.size(); ++i) {
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(filenames[i].second);
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(filenames[i].second());
if(!data) {
Error() << "ShaderTools::AbstractConverter::linkFilesToData(): cannot open file" << filenames[i].second;
Error() << "ShaderTools::AbstractConverter::linkFilesToData(): cannot open file" << filenames[i].second();
return {};
}
@ -729,10 +730,10 @@ Containers::Optional<Containers::Array<char>> AbstractConverter::doLinkFilesToDa
}
/** @todo merge the allocations once we have an ArrayTuple */
Containers::Array<std::pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.size()};
Containers::Array<Containers::Pair<Stage, Containers::ArrayView<const char>>> data{NoInit, filenames.size()};
for(std::size_t i = 0; i != filenames.size(); ++i) {
data[i].first = filenames[i].first;
data[i].second = fileData[i];
data[i].first() = filenames[i].first();
data[i].second() = fileData[i];
}
return doLinkDataToData(data);

45
src/Magnum/ShaderTools/AbstractConverter.h

@ -41,6 +41,13 @@
/* 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
@ -720,10 +727,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* in @ref magnum-shaderconverter "magnum-shaderconverter".
* @see @ref ConverterFlag::PreprocessOnly
*/
void setDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions);
void setDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions);
/** @overload */
void setDefinitions(std::initializer_list<std::pair<Containers::StringView, Containers::StringView>> definitions);
void setDefinitions(std::initializer_list<Containers::Pair<Containers::StringView, Containers::StringView>> definitions);
/**
* @brief Set optimization level
@ -778,7 +785,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
*
* @see @ref features(), @ref validateFile()
*/
std::pair<bool, Containers::String> validateData(Stage stage, Containers::ArrayView<const void> data);
Containers::Pair<bool, Containers::String> validateData(Stage stage, Containers::ArrayView<const void> data);
/**
* @brief Validate a shader
@ -799,7 +806,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* @ref magnum-shaderconverter "magnum-shaderconverter".
* @see @ref features(), @ref validateData()
*/
std::pair<bool, Containers::String> validateFile(Stage stage, Containers::StringView filename);
Containers::Pair<bool, Containers::String> validateFile(Stage stage, Containers::StringView filename);
/**
* @brief Convert shader data to a data
@ -874,7 +881,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else
Implementation::OptionalButAlsoArray<char>
#endif
linkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data);
linkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data);
/** @overload */
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT)
@ -882,7 +889,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else
Implementation::OptionalButAlsoArray<char>
#endif
linkDataToData(std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data);
linkDataToData(std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data);
/**
* @brief Link shader data together to a file
@ -895,10 +902,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* @see @ref features(), @ref linkFilesToFile(),
* @ref linkFilesToData(), @ref linkDataToData()
*/
bool linkDataToFile(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename);
bool linkDataToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename);
/** @overload */
bool linkDataToFile(std::initializer_list<std::pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename);
bool linkDataToFile(std::initializer_list<Containers::Pair<Stage, Containers::ArrayView<const void>>> data, Containers::StringView filename);
/**
* @brief Link shader files together to a file
@ -914,10 +921,10 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* @see @ref features(), @ref linkFilesToData(), @ref linkDataToFile(),
* @ref linkDataToData()
*/
bool linkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to);
bool linkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to);
/** @overload */
bool linkFilesToFile(std::initializer_list<std::pair<Stage, Containers::StringView>> from, Containers::StringView to);
bool linkFilesToFile(std::initializer_list<Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to);
/**
* @brief Link shader files together to a data
@ -935,7 +942,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else
Implementation::OptionalButAlsoArray<char>
#endif
linkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames);
linkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames);
/** @overload */
#if !defined(MAGNUM_BUILD_DEPRECATED) || defined(DOXYGEN_GENERATING_OUTPUT)
@ -943,7 +950,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
#else
Implementation::OptionalButAlsoArray<char>
#endif
linkFilesToData(std::initializer_list<std::pair<Stage, Containers::StringView>> filenames);
linkFilesToData(std::initializer_list<Containers::Pair<Stage, Containers::StringView>> filenames);
protected:
/**
@ -961,7 +968,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* is not supported --- instead, file is loaded though the callback and
* data passed through to @ref doValidateData().
*/
virtual std::pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename);
virtual Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename);
/**
* @brief Implementation for @ref convertFileToFile()
@ -1012,7 +1019,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* 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);
virtual bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to);
/**
* @brief Implementation for @ref linkFilesToData()
@ -1029,7 +1036,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* 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 std::pair<Stage, Containers::StringView>> filenames);
virtual Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> filenames);
private:
/**
@ -1100,7 +1107,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* Has to be implemented if @ref ConverterFeature::Preprocess is
* supported. This function isn't expected to fail.
*/
virtual void doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions);
virtual void doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions);
/**
* @brief Implementation for @ref setOptimizationLevel()
@ -1136,7 +1143,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* order to accept any type, this function gets it cast to
* @cpp char @ce for more convenience.
*/
virtual std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data);
virtual Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data);
/* Used by convertFileToFile(), doConvertFileToFile(),
convertFileToData() and doConvertFileToData() */
@ -1154,7 +1161,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
/* Used by linkFilesToFile(), doLinkFilesToFile(), linkFilesToData()
and doLinkFilesToData() */
MAGNUM_SHADERTOOLS_LOCAL Containers::Optional<Containers::Array<char>> linkDataToDataUsingInputFileCallbacks(const char* prefix, Containers::ArrayView<const std::pair<Stage, Containers::StringView>> filenames);
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()
@ -1164,7 +1171,7 @@ class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::Abstrac
* 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 std::pair<Stage, Containers::ArrayView<const char>>> data);
virtual Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data);
ConverterFlags _flags;

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

@ -26,6 +26,7 @@
#include <sstream>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h> /** @todo remove once Debug is stream-free */
#include <Corrade/TestSuite/Tester.h>
@ -504,7 +505,7 @@ void AbstractConverterTest::setDefinitions() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
void doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) override {
void doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) override {
howManyIsThere = definitions.size();
}
@ -679,14 +680,14 @@ void AbstractConverterTest::validateData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override {
Containers::Pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override {
return {data.size() == 5*4 && stage == Stage::MeshTask, "Yes, this is valid"};
}
} converter;
std::pair<bool, Containers::String> out = converter.validateData(Stage::MeshTask, Containers::arrayView<UnsignedInt>({0x07230203, 99, 0xcafebabeu, 50, 0}));
CORRADE_VERIFY(out.first);
CORRADE_COMPARE(out.second, "Yes, this is valid");
Containers::Pair<bool, Containers::String> out = converter.validateData(Stage::MeshTask, Containers::arrayView<UnsignedInt>({0x07230203, 99, 0xcafebabeu, 50, 0}));
CORRADE_VERIFY(out.first());
CORRADE_COMPARE(out.second(), "Yes, this is valid");
}
void AbstractConverterTest::validateDataNotSupported() {
@ -759,15 +760,8 @@ void AbstractConverterTest::validateDataCustomStringDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(Stage, const Containers::ArrayView<const char>) override {
/* libc++ and MSVC STL is STUPID and doing
`return {{}, Containers::String{...}};`
will do a COPY, even though not needed. That then of course
discards the custom deleter and makes the test fail. Oh C++, do
I really have to reimplement even std::pair, FFS?! */
std::pair<bool, Containers::String> out;
out.second = Containers::String{"", 0, [](char*, std::size_t){}};
return out;
Containers::Pair<bool, Containers::String> doValidateData(Stage, const Containers::ArrayView<const char>) override {
return {{}, Containers::String{"", 0, [](char*, std::size_t){}}};
}
} converter;
@ -785,14 +779,14 @@ void AbstractConverterTest::validateFile() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(const Stage stage, const Containers::StringView filename) override {
Containers::Pair<bool, Containers::String> doValidateFile(const Stage stage, const Containers::StringView filename) override {
return {stage == Stage::Vertex && filename.size() == 8, "Yes, this is valid"};
}
} converter;
std::pair<bool, Containers::String> out = converter.validateFile(Stage::Vertex, "file.spv");
CORRADE_VERIFY(out.first);
CORRADE_COMPARE(out.second, "Yes, this is valid");
Containers::Pair<bool, Containers::String> out = converter.validateFile(Stage::Vertex, "file.spv");
CORRADE_VERIFY(out.first());
CORRADE_COMPARE(out.second(), "Yes, this is valid");
}
void AbstractConverterTest::validateFileAsData() {
@ -803,14 +797,14 @@ void AbstractConverterTest::validateFileAsData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override {
Containers::Pair<bool, Containers::String> doValidateData(const Stage stage, const Containers::ArrayView<const char> data) override {
return {stage == Stage::Compute && data.size() == 5, "Yes, this is valid"};
}
} converter;
std::pair<bool, Containers::String> out = converter.validateFile(Stage::Compute, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat"));
CORRADE_VERIFY(out.first);
CORRADE_COMPARE(out.second, "Yes, this is valid");
Containers::Pair<bool, Containers::String> out = converter.validateFile(Stage::Compute, Utility::Path::join(SHADERTOOLS_TEST_DIR, "file.dat"));
CORRADE_VERIFY(out.first());
CORRADE_COMPARE(out.second(), "Yes, this is valid");
}
void AbstractConverterTest::validateFileAsDataNotFound() {
@ -821,7 +815,7 @@ void AbstractConverterTest::validateFileAsDataNotFound() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
Containers::Pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
@ -829,9 +823,9 @@ void AbstractConverterTest::validateFileAsDataNotFound() {
std::ostringstream out;
Error redirectError{&out};
std::pair<bool, Containers::String> out2 = converter.validateFile({}, "nonexistent.bin");
CORRADE_VERIFY(!out2.first);
CORRADE_COMPARE(out2.second, "");
Containers::Pair<bool, Containers::String> out2 = converter.validateFile({}, "nonexistent.bin");
CORRADE_VERIFY(!out2.first());
CORRADE_COMPARE(out2.second(), "");
/* There's an error message from Path::read() before */
CORRADE_COMPARE_AS(out.str(),
"\nShaderTools::AbstractConverter::validateFile(): cannot open file nonexistent.bin\n",
@ -908,15 +902,8 @@ void AbstractConverterTest::validateFileCustomStringDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, Containers::StringView) override {
/* libc++ and MSVC STL is STUPID and doing
`return {{}, Containers::String{...}};`
will do a COPY, even though not needed. That then of course
discards the custom deleter and makes the test fail. Oh C++, do
I really have to reimplement even std::pair, FFS?! */
std::pair<bool, Containers::String> out;
out.second = Containers::String{"", 0, [](char*, std::size_t){}};
return out;
Containers::Pair<bool, Containers::String> doValidateFile(Stage, Containers::StringView) override {
return {{}, Containers::String{"", 0, [](char*, std::size_t){}}};
}
} converter;
@ -1412,11 +1399,11 @@ void AbstractConverterTest::linkDataToData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
} converter;
@ -1467,7 +1454,7 @@ void AbstractConverterTest::linkDataToDataNotImplemented() {
std::ostringstream out;
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkDataToData({std::pair<Stage, Containers::ArrayView<const void>>{}});
converter.linkDataToData({Containers::Pair<Stage, Containers::ArrayView<const void>>{}});
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented\n");
}
@ -1522,7 +1509,7 @@ void AbstractConverterTest::linkDataToDataCustomDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{nullptr, 0, [](char*, std::size_t){}};
}
} converter;
@ -1530,7 +1517,7 @@ void AbstractConverterTest::linkDataToDataCustomDeleter() {
std::ostringstream out;
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkDataToData({std::pair<Stage, Containers::ArrayView<const void>>{}});
converter.linkDataToData({Containers::Pair<Stage, Containers::ArrayView<const void>>{}});
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): implementation is not allowed to use a custom Array deleter\n");
}
@ -1542,11 +1529,11 @@ void AbstractConverterTest::linkDataToFileThroughData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
} converter;
@ -1572,7 +1559,7 @@ void AbstractConverterTest::linkDataToFileThroughDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return {};
}
} converter;
@ -1587,7 +1574,7 @@ void AbstractConverterTest::linkDataToFileThroughDataFailed() {
std::ostringstream out;
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
CORRADE_VERIFY(!converter.linkDataToFile({std::pair<Stage, Containers::ArrayView<const void>>{}}, filename));
CORRADE_VERIFY(!converter.linkDataToFile({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}, filename));
CORRADE_VERIFY(!Utility::Path::exists(filename));
CORRADE_COMPARE(out.str(), "");
}
@ -1600,7 +1587,7 @@ void AbstractConverterTest::linkDataToFileThroughDataNotWritable() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{1};
}
} converter;
@ -1608,7 +1595,7 @@ void AbstractConverterTest::linkDataToFileThroughDataNotWritable() {
std::ostringstream out;
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
CORRADE_VERIFY(!converter.linkDataToFile({std::pair<Stage, Containers::ArrayView<const void>>{}}, "/some/path/that/does/not/exist"));
CORRADE_VERIFY(!converter.linkDataToFile({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}, "/some/path/that/does/not/exist"));
CORRADE_COMPARE_AS(out.str(),
"ShaderTools::AbstractConverter::linkDataToFile(): cannot write to file /some/path/that/does/not/exist\n",
TestSuite::Compare::StringHasSuffix);
@ -1649,7 +1636,7 @@ void AbstractConverterTest::linkDataToFileNotImplemented() {
std::ostringstream out;
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkDataToFile({std::pair<Stage, Containers::ArrayView<const void>>{}}, "file.dat");
converter.linkDataToFile({Containers::Pair<Stage, Containers::ArrayView<const void>>{}}, "file.dat");
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkDataToData(): feature advertised but not implemented\n");
}
@ -1700,15 +1687,15 @@ void AbstractConverterTest::linkFilesToFile() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
CORRADE_COMPARE(from.size(), 2);
Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second);
Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second);
Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second());
Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second());
CORRADE_VERIFY(first);
CORRADE_VERIFY(second);
return Utility::Path::write(to, Containers::array({
from[0].first == Stage::Vertex ? (*first)[0] : ' ',
from[1].first == Stage::Fragment ? (*second)[0] : ' '
from[0].first() == Stage::Vertex ? (*first)[0] : ' ',
from[1].first() == Stage::Fragment ? (*second)[0] : ' '
}));
}
} converter;
@ -1736,11 +1723,11 @@ void AbstractConverterTest::linkFilesToFileThroughData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
} converter;
@ -1766,7 +1753,7 @@ void AbstractConverterTest::linkFilesToFileThroughDataNotFound() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
@ -1792,7 +1779,7 @@ void AbstractConverterTest::linkFilesToFileThroughDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return {};
}
} converter;
@ -1821,7 +1808,7 @@ void AbstractConverterTest::linkFilesToFileThroughDataNotWritable() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{1};
}
} converter;
@ -1871,7 +1858,7 @@ void AbstractConverterTest::linkFilesToFileNotImplemented() {
std::ostringstream out;
Error redirectError{&out};
/* {{}} makes GCC 4.8 warn about zero as null pointer constant */
converter.linkFilesToFile({std::pair<Stage, Containers::StringView>{}}, {});
converter.linkFilesToFile({Containers::Pair<Stage, Containers::StringView>{}}, {});
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::linkFilesToFile(): feature advertised but not implemented\n");
}
@ -1922,15 +1909,15 @@ void AbstractConverterTest::linkFilesToData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override {
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
CORRADE_COMPARE(from.size(), 2);
Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second);
Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second);
Containers::Optional<Containers::Array<char>> first = Utility::Path::read(from[0].second());
Containers::Optional<Containers::Array<char>> second = Utility::Path::read(from[1].second());
CORRADE_VERIFY(first);
CORRADE_VERIFY(second);
return Containers::array({
from[0].first == Stage::Vertex ? (*first)[0] : ' ',
from[1].first == Stage::Fragment ? (*second)[0] : ' '
from[0].first() == Stage::Vertex ? (*first)[0] : ' ',
from[1].first() == Stage::Fragment ? (*second)[0] : ' '
});
}
} converter;
@ -1954,11 +1941,11 @@ void AbstractConverterTest::linkFilesToDataAsData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
} converter;
@ -1982,7 +1969,7 @@ void AbstractConverterTest::linkFilesToDataAsDataNotFound() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
@ -2092,7 +2079,7 @@ void AbstractConverterTest::linkFilesToDataCustomDeleter() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>) override {
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>) override {
return Containers::Array<char>{nullptr, 0, [](char*, std::size_t){}};
}
} converter;
@ -2255,11 +2242,11 @@ void AbstractConverterTest::setInputFileCallbackValidateFileDirectly() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView filename) override {
Containers::Pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView filename) override {
return {filename == "file.dat" && inputFileCallback() && inputFileCallbackUserData(), "it's what it is!"};
}
std::pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
Containers::Pair<bool, Containers::String> doValidateData(Stage, Containers::ArrayView<const char>) override {
CORRADE_VERIFY(!"this should not be reached");
return {};
}
@ -2271,7 +2258,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileDirectly() {
return Containers::Optional<Containers::ArrayView<const char>>{};
}, &a);
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), std::make_pair(true, "it's what it is!"));
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), Containers::pair(true, Containers::String{"it's what it is!"}));
}
void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplementation() {
@ -2282,7 +2269,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override {
Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override {
validateFileCalled = true;
if(filename != "file.dat" || !inputFileCallback() || !inputFileCallbackUserData())
@ -2291,7 +2278,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
return AbstractConverter::doValidateFile(stage, filename);
}
std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override {
Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override {
return {stage == Stage::RayCallable && data.size() == 1 && data[0] == '\xb0', "yep!!"};
}
@ -2319,7 +2306,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
return {};
}, state);
CORRADE_COMPARE(converter.validateFile(Stage::RayCallable, "file.dat"), std::make_pair(true, "yep!!"));
CORRADE_COMPARE(converter.validateFile(Stage::RayCallable, "file.dat"), Containers::pair(true, Containers::String{"yep!!"}));
CORRADE_VERIFY(converter.validateFileCalled);
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
@ -2333,7 +2320,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override {
Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, const Containers::StringView filename) override {
validateFileCalled = true;
return AbstractConverter::doValidateFile(stage, filename);
}
@ -2348,7 +2335,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileThroughBaseImplement
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), std::make_pair(false, ""));
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), Containers::pair(false, Containers::String{}));
CORRADE_VERIFY(converter.validateFileCalled);
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::validateFile(): cannot open file file.dat\n");
}
@ -2361,12 +2348,12 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override {
Containers::Pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override {
Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override {
return {stage == Stage::Fragment && data.size() == 1 && data[0] == '\xb0', "yep!!"};
}
} converter;
@ -2392,7 +2379,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsData() {
return {};
}, state);
CORRADE_COMPARE(converter.validateFile(Stage::Fragment, "file.dat"), std::make_pair(true, "yep!!"));
CORRADE_COMPARE(converter.validateFile(Stage::Fragment, "file.dat"), Containers::pair(true, Containers::String{"yep!!"}));
CORRADE_VERIFY(state.loaded);
CORRADE_VERIFY(state.closed);
}
@ -2405,7 +2392,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
std::pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override {
Containers::Pair<bool, Containers::String> doValidateFile(Stage, const Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
@ -2418,7 +2405,7 @@ void AbstractConverterTest::setInputFileCallbackValidateFileAsDataFailed() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), std::make_pair(false, ""));
CORRADE_COMPARE(converter.validateFile({}, "file.dat"), Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), "ShaderTools::AbstractConverter::validateFile(): cannot open file file.dat\n");
}
@ -2863,8 +2850,8 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileDirectly() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
return from.size() == 2 && from[0].first == Stage::Vertex && from[0].second == "another.dat" && from[1].first == Stage::Fragment && from[1].second == "file.dat" && to == "file.out" && inputFileCallback() && inputFileCallbackUserData();
bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
return from.size() == 2 && from[0].first() == Stage::Vertex && from[0].second() == "another.dat" && from[1].first() == Stage::Fragment && from[1].second() == "file.dat" && to == "file.out" && inputFileCallback() && inputFileCallbackUserData();
}
Containers::Optional<Containers::Array<char>> doConvertDataToData(Stage, Containers::ArrayView<const char>) override {
@ -2893,20 +2880,20 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
linkFilesToFileCalled = true;
if(from.size() != 2 || from[0].first != Stage::Vertex || from[0].second != "another.dat" || from[1].first != Stage::Fragment || from[1].second != "file.dat" || !to.hasSuffix("file.out") || !inputFileCallback() || !inputFileCallbackUserData())
if(from.size() != 2 || from[0].first() != Stage::Vertex || from[0].second() != "another.dat" || from[1].first() != Stage::Fragment || from[1].second() != "file.dat" || !to.hasSuffix("file.out") || !inputFileCallback() || !inputFileCallbackUserData())
return {};
return AbstractConverter::doLinkFilesToFile(from, to);
}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
@ -2963,12 +2950,12 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from, Containers::StringView to) override {
linkFilesToFileCalled = true;
return AbstractConverter::doLinkFilesToFile(from, to);
}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this shouldn't be called");
return {};
}
@ -3022,16 +3009,16 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileAsData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>, Containers::StringView) override {
bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>, Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
} converter;
@ -3085,7 +3072,7 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileAsDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>, Containers::StringView) override {
bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>, Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
@ -3132,12 +3119,12 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToFileAsDataNotWritable
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
bool doLinkFilesToFile(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>, Containers::StringView) override {
bool doLinkFilesToFile(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>, Containers::StringView) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
return Containers::Array<char>{1};
}
} converter;
@ -3190,13 +3177,13 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataDirectly() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override {
if(from.size() == 2 && from[0].first == Stage::Vertex && from[0].second == "another.dat" && from[1].first == Stage::Fragment && from[1].second == "file.dat" && inputFileCallback() && inputFileCallbackUserData())
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
if(from.size() == 2 && from[0].first() == Stage::Vertex && from[0].second() == "another.dat" && from[1].first() == Stage::Fragment && from[1].second() == "file.dat" && inputFileCallback() && inputFileCallbackUserData())
return Containers::array({'y', 'e', 'p'});
return {};
}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>>) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>>) override {
CORRADE_VERIFY(!"this should not be reached");
return {};
}
@ -3226,20 +3213,20 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override {
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
linkFilesToDataCalled = true;
if(from.size() != 2 || from[0].first != Stage::Vertex || from[0].second != "another.dat" || from[1].first != Stage::Fragment || from[1].second != "file.dat" || !inputFileCallback() || !inputFileCallbackUserData())
if(from.size() != 2 || from[0].first() != Stage::Vertex || from[0].second() != "another.dat" || from[1].first() != Stage::Fragment || from[1].second() != "file.dat" || !inputFileCallback() || !inputFileCallbackUserData())
return {};
return AbstractConverter::doLinkFilesToData(from);
}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
@ -3294,7 +3281,7 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataThroughBaseImplem
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>> from) override {
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>> from) override {
linkFilesToDataCalled = true;
return AbstractConverter::doLinkFilesToData(from);
}
@ -3348,16 +3335,16 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataAsData() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>) override {
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const std::pair<Stage, Containers::ArrayView<const char>>> data) override {
Containers::Optional<Containers::Array<char>> doLinkDataToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::ArrayView<const char>>> data) override {
CORRADE_COMPARE(data.size(), 2);
return Containers::array({
data[0].first == Stage::Vertex ? data[0].second[0] : ' ',
data[1].first == Stage::Fragment ? data[1].second[0] : ' '
data[0].first() == Stage::Vertex ? data[0].second()[0] : ' ',
data[1].first() == Stage::Fragment ? data[1].second()[0] : ' '
});
}
} converter;
@ -3409,7 +3396,7 @@ void AbstractConverterTest::setInputFileCallbackLinkFilesToDataAsDataFailed() {
void doSetInputFormat(Format, Containers::StringView) override {}
void doSetOutputFormat(Format, Containers::StringView) override {}
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const std::pair<Stage, Containers::StringView>>) override {
Containers::Optional<Containers::Array<char>> doLinkFilesToData(Containers::ArrayView<const Containers::Pair<Stage, Containers::StringView>>) override {
CORRADE_VERIFY(!"this shouldn't be reached");
return {};
}

17
src/Magnum/ShaderTools/shaderconverter.cpp

@ -25,6 +25,7 @@
#include <Corrade/Containers/GrowableArray.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Utility/Arguments.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/Path.h>
@ -421,7 +422,7 @@ see documentation of a particular converter for more information.)")
/* Options and flags applied just for the first converter; setting up
file list for linking */
Containers::Array<std::pair<ShaderTools::Stage, Containers::StringView>> linkInputs;
Containers::Array<Containers::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)) {
@ -432,7 +433,7 @@ see documentation of a particular converter for more information.)")
if(args.isSet("preprocess-only"))
flags |= ShaderTools::ConverterFlag::PreprocessOnly;
Containers::Array<std::pair<Containers::StringView, Containers::StringView>> definitions;
Containers::Array<Containers::Pair<Containers::StringView, Containers::StringView>> definitions;
arrayReserve(definitions, args.arrayValueCount("define") + args.arrayValueCount("undefine"));
for(std::size_t j = 0; j != args.arrayValueCount("define"); ++j) {
const Containers::Array3<Containers::StringView> define =
@ -516,18 +517,18 @@ see documentation of a particular converter for more information.)")
return 13;
}
std::pair<bool, Containers::String> out = converter->validateFile(ShaderTools::Stage::Unspecified, args.arrayValue<Containers::StringView>("input", 0));
if(!out.first) {
Containers::Pair<bool, Containers::String> out = converter->validateFile(ShaderTools::Stage::Unspecified, args.arrayValue<Containers::StringView>("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(!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;
if(!out.second().isEmpty()) Warning{} << out.second();
} else if(args.isSet("verbose"))
Debug{} << "Validation passed";
return out.first ? 0 : 14;
return out.first() ? 0 : 14;
}
/** @todo ability to specify the stage (need a configurationvalue parser for this) */

24
src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp

@ -44,8 +44,8 @@ struct AnyConverter::State {
Format inputFormat, outputFormat;
Containers::String inputVersion, outputVersion;
Containers::Array<std::pair<Containers::String, Containers::String>> definitions;
Containers::Array<std::pair<Containers::StringView, Containers::StringView>> definitionViews;
Containers::Array<Containers::Pair<Containers::String, Containers::String>> definitions;
Containers::Array<Containers::Pair<Containers::StringView, Containers::StringView>> definitionViews;
Containers::String debugInfoLevel, optimizationLevel;
};
@ -70,23 +70,23 @@ void AnyConverter::doSetOutputFormat(Format format, Containers::StringView versi
_state->outputVersion = Containers::String::nullTerminatedGlobalView(version);
}
void AnyConverter::doSetDefinitions(const Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) {
void AnyConverter::doSetDefinitions(const Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) {
/* We have to make a local copy, unfortunately, and then a view on that
local copy */
_state->definitions = Containers::Array<std::pair<Containers::String, Containers::String>>{definitions.size()};
_state->definitionViews = Containers::Array<std::pair<Containers::StringView, Containers::StringView>>{definitions.size()};
_state->definitions = Containers::Array<Containers::Pair<Containers::String, Containers::String>>{definitions.size()};
_state->definitionViews = Containers::Array<Containers::Pair<Containers::StringView, Containers::StringView>>{definitions.size()};
for(std::size_t i = 0; i != definitions.size(); ++i) {
/* Avoid a copy if the input is a global string literal */
_state->definitions[i] = {
Containers::String::nullTerminatedGlobalView(definitions[i].first),
Containers::String::nullTerminatedGlobalView(definitions[i].second)
Containers::String::nullTerminatedGlobalView(definitions[i].first()),
Containers::String::nullTerminatedGlobalView(definitions[i].second())
};
/* Preserve the distinction between empty defines ("") and undefines
(nullptr or default constructor) */
_state->definitionViews[i] = {
_state->definitions[i].first,
definitions[i].second.data() ?
Containers::StringView{_state->definitions[i].second} :
_state->definitions[i].first(),
definitions[i].second().data() ?
Containers::StringView{_state->definitions[i].second()} :
Containers::StringView{}
};
}
@ -175,7 +175,7 @@ Format formatForExtension(const char* prefix, const Containers::StringView filen
}
std::pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage stage, const Containers::StringView filename) {
Containers::Pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage stage, const Containers::StringView filename) {
CORRADE_INTERNAL_ASSERT(manager());
/* Prefer the explicitly set input format. If not set, fall back to
@ -235,7 +235,7 @@ std::pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage sta
return converter->validateFile(stage, filename);
}
std::pair<bool, Containers::String> AnyConverter::doValidateData(const Stage stage, const Containers::ArrayView<const char> data) {
Containers::Pair<bool, Containers::String> AnyConverter::doValidateData(const Stage stage, const Containers::ArrayView<const char> data) {
CORRADE_INTERNAL_ASSERT(manager());
/* Decide on a plugin name based on the format */

6
src/MagnumPlugins/AnyShaderConverter/AnyConverter.h

@ -155,12 +155,12 @@ class MAGNUM_ANYSHADERCONVERTER_EXPORT AnyConverter: public AbstractConverter {
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetInputFormat(Format, Containers::StringView version) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOutputFormat(Format, Containers::StringView version) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDefinitions(Containers::ArrayView<const std::pair<Containers::StringView, Containers::StringView>> definitions) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDefinitions(Containers::ArrayView<const Containers::Pair<Containers::StringView, Containers::StringView>> definitions) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetDebugInfoLevel(Containers::StringView level) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL void doSetOptimizationLevel(Containers::StringView level) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Optional<Containers::Array<char>> doConvertFileToData(Magnum::ShaderTools::Stage stage, Containers::StringView filename) override;
MAGNUM_ANYSHADERCONVERTER_LOCAL Containers::Optional<Containers::Array<char>> doConvertDataToData(Magnum::ShaderTools::Stage stage, Containers::ArrayView<const char> data) override;

49
src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp

@ -26,6 +26,7 @@
#include <sstream>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/Pair.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/PluginManager/Manager.h>
@ -264,7 +265,7 @@ void AnyConverterTest::validateFile() {
/* Make it print a warning so we know it's doing something */
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(true, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
Containers::pair(true, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
}
void AnyConverterTest::validateFilePluginLoadFailed() {
@ -273,7 +274,7 @@ void AnyConverterTest::validateFilePluginLoadFailed() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, "file.glsl"),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n"
@ -291,7 +292,7 @@ void AnyConverterTest::validateFileUnknown() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, "dead.cg"),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateFile(): cannot determine the format of dead.cg\n");
}
@ -317,7 +318,7 @@ void AnyConverterTest::validateFilePreprocessNotSupported() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.spv")),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateFile(): SpirvToolsShaderConverter does not support preprocessing\n");
}
@ -342,7 +343,7 @@ void AnyConverterTest::validateFilePropagateFlags() {
std::ostringstream out;
Debug redirectDebug{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(false, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
Containers::pair(false, Utility::format("WARNING: {}:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateFile(): using GlslShaderConverter (provided by GlslangShaderConverter)\n");
}
@ -366,7 +367,7 @@ void AnyConverterTest::validateFilePropagateInputVersion() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n");
}
@ -390,7 +391,7 @@ void AnyConverterTest::validateFilePropagateOutputVersion() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n");
}
@ -417,7 +418,7 @@ void AnyConverterTest::validateFilePropagatePreprocess() {
});
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(true, Utility::format("WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
Containers::pair(true, Utility::format("WARNING: {}:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved", filename)));
}
void AnyConverterTest::validateFilePropagateConfiguration() {
@ -435,13 +436,13 @@ void AnyConverterTest::validateFilePropagateConfiguration() {
{
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(false, Utility::format("ERROR: {}:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated.", filename)));
Containers::pair(false, Utility::format("ERROR: {}:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated.", filename)));
} {
converter->configuration().setValue("permissive", true);
/* Lol stupid thing, apparently it has two differently worded messages
for the same thing? Dumpster fire. */
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, filename),
std::make_pair(true, "WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version"));
Containers::pair(true, Containers::String{"WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version"}));
}
}
@ -462,7 +463,7 @@ void AnyConverterTest::validateFilePropagateConfigurationUnknown() {
std::ostringstream out;
Warning redirectWarning{&out};
CORRADE_COMPARE(converter->validateFile(Stage::Fragment, Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl")),
std::make_pair(true, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateFile(): option noSuchOption not recognized by GlslangShaderConverter\n");
}
@ -484,7 +485,7 @@ void AnyConverterTest::validateData() {
Containers::Optional<Containers::Array<char>> data = Utility::Path::read(Utility::Path::join(ANYSHADERCONVERTER_TEST_DIR, "file.glsl"));
CORRADE_VERIFY(data);
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved"));
Containers::pair(true, Containers::String{"WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved"}));
}
void AnyConverterTest::validateDataPluginLoadFailed() {
@ -495,7 +496,7 @@ void AnyConverterTest::validateDataPluginLoadFailed() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateData({}, {}),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin GlslShaderConverter is not static and was not found in nonexistent\n"
@ -513,7 +514,7 @@ void AnyConverterTest::validateDataNoFormatSet() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateData({}, "dead.cg"),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(), "ShaderTools::AnyConverter::validateData(): no input format specified\n");
}
@ -544,7 +545,7 @@ void AnyConverterTest::validateDataPreprocessNotSupported() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateData({}, *data),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateData(): SpirvToolsShaderConverter does not support preprocessing\n");
}
@ -572,7 +573,7 @@ void AnyConverterTest::validateDataPropagateFlags() {
std::ostringstream out;
Debug redirectDebug{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, "WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved"));
Containers::pair(false, Containers::String{"WARNING: 0:10: 'reserved__identifier' : identifiers containing consecutive underscores (\"__\") are reserved"}));
CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateData(): using GlslShaderConverter (provided by GlslangShaderConverter)\n");
}
@ -601,7 +602,7 @@ void AnyConverterTest::validateDataPropagateInputVersion() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): input format version should be one of supported GLSL #version strings but got 100\n");
}
@ -630,7 +631,7 @@ void AnyConverterTest::validateDataPropagateOutputVersion() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::GlslangConverter::validateData(): output format should be Spirv or Unspecified but got ShaderTools::Format::Glsl\n");
}
@ -660,7 +661,7 @@ void AnyConverterTest::validateDataPropagatePreprocess() {
CORRADE_VERIFY(data);
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, "WARNING: 0:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved"));
Containers::pair(true, Containers::String{"WARNING: 0:10: 'different__but_also_wrong' : identifiers containing consecutive underscores (\"__\") are reserved"}));
}
void AnyConverterTest::validateDataPropagateConfiguration() {
@ -680,13 +681,13 @@ void AnyConverterTest::validateDataPropagateConfiguration() {
{
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(false, "ERROR: 0:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated."));
Containers::pair(false, Containers::String{"ERROR: 0:2: '#version' : must occur first in shader \nERROR: 1 compilation errors. No code generated."}));
} {
converter->configuration().setValue("permissive", true);
/* Lol stupid thing, apparently it has two differently worded messages
for the same thing? Dumpster fire. */
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, Utility::format("WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version")));
Containers::pair(true, Utility::format("WARNING: 0:0: '#version' : Illegal to have non-comment, non-whitespace tokens before #version")));
}
}
@ -711,7 +712,7 @@ void AnyConverterTest::validateDataPropagateConfigurationUnknown() {
std::ostringstream out;
Warning redirectWarning{&out};
CORRADE_COMPARE(converter->validateData(Stage::Fragment, *data),
std::make_pair(true, ""));
Containers::pair(false, Containers::String{}));
CORRADE_COMPARE(out.str(),
"ShaderTools::AnyConverter::validateData(): option noSuchOption not recognized by GlslangShaderConverter\n");
}
@ -1856,7 +1857,7 @@ void AnyConverterTest::detectValidate() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, data.filename),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(), Utility::formatString(
"PluginManager::Manager::load(): plugin {0} is not static and was not found in nonexistent\n"
@ -1877,7 +1878,7 @@ void AnyConverterTest::detectValidateExplicitFormat() {
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, "file.spv"),
std::make_pair(false, ""));
Containers::pair(false, Containers::String{}));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin HlslShaderConverter is not static and was not found in nonexistent\n"

Loading…
Cancel
Save