Browse Source

AnyShaderConverter: take explicitly set formats into account.

So if we convert foo.blah but explicitly tell it that it's a SPIR-V
file, it actually treats it as such, instead of complaining that `blah`
is not a known extension.

First step towards being able to operate directly on data.
pull/495/head
Vladimír Vondruš 5 years ago
parent
commit
7220274ff3
  1. 53
      src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp
  2. 6
      src/MagnumPlugins/AnyShaderConverter/AnyConverter.h
  3. 48
      src/MagnumPlugins/AnyShaderConverter/Test/AnyConverterTest.cpp

53
src/MagnumPlugins/AnyShaderConverter/AnyConverter.cpp

@ -101,7 +101,25 @@ namespace {
using namespace Containers::Literals; using namespace Containers::Literals;
Containers::StringView formatForExtension(const char* prefix, const Containers::StringView filename) { Containers::StringView stringForFormat(const Format format) {
switch(format) {
#define _c(format) case Format::format: return #format ## _s;
_c(Glsl)
_c(Spirv)
_c(SpirvAssembly)
_c(Hlsl)
_c(Msl)
_c(Wgsl)
_c(Dxil)
#undef _c
case Format::Unspecified: return {};
}
CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
Format formatForExtension(const char* prefix, const Containers::StringView filename) {
/** @todo lowercase only the extension, once Directory::split() is done */ /** @todo lowercase only the extension, once Directory::split() is done */
const std::string normalized = Utility::String::lowercase(filename); const std::string normalized = Utility::String::lowercase(filename);
@ -126,7 +144,7 @@ Containers::StringView formatForExtension(const char* prefix, const Containers::
Utility::String::endsWith(normalized, ".asm.rcall") || Utility::String::endsWith(normalized, ".asm.rcall") ||
Utility::String::endsWith(normalized, ".asm.mesh") || Utility::String::endsWith(normalized, ".asm.mesh") ||
Utility::String::endsWith(normalized, ".asm.task")) Utility::String::endsWith(normalized, ".asm.task"))
return "SpirvAssembly"_s; return Format::SpirvAssembly;
/* https://github.com/KhronosGroup/glslang/blob/3ce148638bdc3807316e358dee4a5c9583189ae7/StandAlone/StandAlone.cpp#L260-L274 */ /* https://github.com/KhronosGroup/glslang/blob/3ce148638bdc3807316e358dee4a5c9583189ae7/StandAlone/StandAlone.cpp#L260-L274 */
else if(Utility::String::endsWith(normalized, ".glsl") || else if(Utility::String::endsWith(normalized, ".glsl") ||
Utility::String::endsWith(normalized, ".vert") || Utility::String::endsWith(normalized, ".vert") ||
@ -143,9 +161,9 @@ Containers::StringView formatForExtension(const char* prefix, const Containers::
Utility::String::endsWith(normalized, ".rcall") || Utility::String::endsWith(normalized, ".rcall") ||
Utility::String::endsWith(normalized, ".mesh") || Utility::String::endsWith(normalized, ".mesh") ||
Utility::String::endsWith(normalized, ".task")) Utility::String::endsWith(normalized, ".task"))
return "Glsl"_s; return Format::Glsl;
else if(Utility::String::endsWith(normalized, ".spv")) else if(Utility::String::endsWith(normalized, ".spv"))
return "Spirv"_s; return Format::Spirv;
Error{} << prefix << "cannot determine the format of" << filename; Error{} << prefix << "cannot determine the format of" << filename;
return {}; return {};
@ -156,9 +174,15 @@ Containers::StringView formatForExtension(const char* prefix, const Containers::
std::pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage stage, const Containers::StringView filename) { std::pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage stage, const Containers::StringView filename) {
CORRADE_INTERNAL_ASSERT(manager()); CORRADE_INTERNAL_ASSERT(manager());
/* Decide on a plugin name based on the extension */ /* Prefer the explicitly set input format. If not set, fall back to
const Containers::StringView format = formatForExtension("ShaderTools::AnyConverter::validateFile():", filename); detecting based on extension. */
const Containers::StringView format = stringForFormat(
_state->inputFormat != Format::Unspecified ? _state->inputFormat :
formatForExtension("ShaderTools::AnyConverter::validateFile():", filename)
);
if(format.isEmpty()) return {}; if(format.isEmpty()) return {};
/* Decide on a plugin name based on the format */
const std::string plugin = Utility::formatString("{}ShaderConverter", format); const std::string plugin = Utility::formatString("{}ShaderConverter", format);
/* Try to load the plugin */ /* Try to load the plugin */
@ -207,12 +231,19 @@ std::pair<bool, Containers::String> AnyConverter::doValidateFile(const Stage sta
bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::StringView from, const Containers::StringView to) { bool AnyConverter::doConvertFileToFile(const Stage stage, const Containers::StringView from, const Containers::StringView to) {
CORRADE_INTERNAL_ASSERT(manager()); CORRADE_INTERNAL_ASSERT(manager());
/* Decide on a plugin name based on the input and output extension. This /* Prefer the explicitly set input format. If not set, fall back to
might result in invalid combinations such as SpirvToGlslShaderConverter detecting based on input and output extension. */
which can't be really handled yet but I think that's okay for now */ const Containers::StringView formatFrom = stringForFormat(
const Containers::StringView formatFrom = formatForExtension("ShaderTools::AnyConverter::convertFileToFile():", from); _state->inputFormat != Format::Unspecified ? _state->inputFormat : formatForExtension("ShaderTools::AnyConverter::convertFileToFile():", from)
const Containers::StringView formatTo = formatForExtension("ShaderTools::AnyConverter::convertFileToFile():", to); );
const Containers::StringView formatTo = stringForFormat(
_state->outputFormat != Format::Unspecified ? _state->outputFormat : formatForExtension("ShaderTools::AnyConverter::convertFileToFile():", to)
);
if(formatFrom.isEmpty() || formatTo.isEmpty()) return {}; if(formatFrom.isEmpty() || formatTo.isEmpty()) return {};
/* Decide on a plugin name based on the format. This might result in
invalid combinations such as SpirvToGlslShaderConverter which can't be
really handled yet but I think that's okay for now. */
const std::string plugin = Utility::formatString( const std::string plugin = Utility::formatString(
formatFrom == formatTo ? "{}ShaderConverter" : "{}To{}ShaderConverter", formatFrom == formatTo ? "{}ShaderConverter" : "{}To{}ShaderConverter",
formatFrom, formatTo); formatFrom, formatTo);

6
src/MagnumPlugins/AnyShaderConverter/AnyConverter.h

@ -57,8 +57,10 @@ namespace Magnum { namespace ShaderTools {
@m_keywords{AnyShaderConverter} @m_keywords{AnyShaderConverter}
Detects file type based on file extension, loads corresponding plugin and then Loads a plugin corresponding to a format either explicitly set using
tries to either validate or convert the file with it. Detected file formats: @ref setInputFormat() / @ref setOutputFormat() or detected based on input /
output file extension plugin and then tries to either validate or convert the
file with it. These formats are detected based on extension:
- GLSL (`*.glsl`, `*.vert`, `*.frag`, `*.geom`, `*.comp`, `*.tesc`, `*.tese`, - GLSL (`*.glsl`, `*.vert`, `*.frag`, `*.geom`, `*.comp`, `*.tesc`, `*.tese`,
`*.rgen`, `*.rint`, `*.rahit`, `*.rchit`, `*.rmiss`, `*.rcall`, `*.mesh`, `*.rgen`, `*.rint`, `*.rahit`, `*.rchit`, `*.rmiss`, `*.rcall`, `*.mesh`,

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

@ -64,7 +64,9 @@ struct AnyConverterTest: TestSuite::Tester {
void convertPropagateOptimization(); void convertPropagateOptimization();
void detectValidate(); void detectValidate();
void detectValidateExplicitFormat();
void detectConvert(); void detectConvert();
void detectConvertExplicitFormat();
void unknown(); void unknown();
@ -120,9 +122,13 @@ AnyConverterTest::AnyConverterTest() {
addInstancedTests({&AnyConverterTest::detectValidate}, addInstancedTests({&AnyConverterTest::detectValidate},
Containers::arraySize(DetectValidateData)); Containers::arraySize(DetectValidateData));
addTests({&AnyConverterTest::detectValidateExplicitFormat});
addInstancedTests({&AnyConverterTest::detectConvert}, addInstancedTests({&AnyConverterTest::detectConvert},
Containers::arraySize(DetectConvertData)); Containers::arraySize(DetectConvertData));
addTests({&AnyConverterTest::detectConvertExplicitFormat});
addTests({&AnyConverterTest::unknown}); addTests({&AnyConverterTest::unknown});
/* Load the plugin directly from the build tree. Otherwise it's static and /* Load the plugin directly from the build tree. Otherwise it's static and
@ -567,6 +573,27 @@ void AnyConverterTest::detectValidate() {
#endif #endif
} }
void AnyConverterTest::detectValidateExplicitFormat() {
Containers::Pointer<AbstractConverter> converter = _manager.instantiate("AnyShaderConverter");
/* It should pick up this format and not bother with the extension */
converter->setInputFormat(Format::Hlsl);
std::ostringstream out;
Error redirectError{&out};
CORRADE_COMPARE(converter->validateFile({}, "file.spv"),
std::make_pair(false, ""));
#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"
"ShaderTools::AnyConverter::validateFile(): cannot load the HlslShaderConverter plugin\n");
#else
CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin HlslShaderConverter was not found\n"
"ShaderTools::AnyConverter::validateFile(): cannot load the HlslShaderConverter plugin\n");
#endif
}
void AnyConverterTest::detectConvert() { void AnyConverterTest::detectConvert() {
auto&& data = DetectConvertData[testCaseInstanceId()]; auto&& data = DetectConvertData[testCaseInstanceId()];
setTestCaseDescription(data.name); setTestCaseDescription(data.name);
@ -587,6 +614,27 @@ void AnyConverterTest::detectConvert() {
#endif #endif
} }
void AnyConverterTest::detectConvertExplicitFormat() {
Containers::Pointer<AbstractConverter> converter = _manager.instantiate("AnyShaderConverter");
/* It should pick up this format and not bother with the extension */
converter->setInputFormat(Format::Hlsl);
converter->setOutputFormat(Format::Wgsl);
std::ostringstream out;
Error redirectError{&out};
CORRADE_VERIFY(!converter->convertFileToFile({}, "file.spv", Utility::Directory::join(ANYSHADERCONVERTER_TEST_OUTPUT_DIR, "file.glsl")));
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin HlslToWgslShaderConverter is not static and was not found in nonexistent\n"
"ShaderTools::AnyConverter::convertFileToFile(): cannot load the HlslToWgslShaderConverter plugin\n");
#else
CORRADE_COMPARE(out.str(),
"PluginManager::Manager::load(): plugin HlslToWgslShaderConverter was not found\n"
"ShaderTools::AnyConverter::convertFileToFile(): cannot load the HlslToWgslShaderConverter plugin\n");
#endif
}
void AnyConverterTest::unknown() { void AnyConverterTest::unknown() {
std::ostringstream output; std::ostringstream output;
Error redirectError{&output}; Error redirectError{&output};

Loading…
Cancel
Save