Browse Source

ShaderTools: bootstrap new library.

Currently there's just a plugin interface for shader converters. More
stuff (probably something like SPIR-V reflection) will come later.
pull/481/head
Vladimír Vondruš 6 years ago
parent
commit
13dfb6472f
  1. 8
      CMakeLists.txt
  2. 1
      doc/building.dox
  3. 6
      doc/changelog.dox
  4. 1
      doc/cmake.dox
  5. 1
      doc/compilation-speedup.dox
  6. 2
      doc/custom-buildsystems-order.dot
  7. 26
      doc/namespaces.dox
  8. 3
      doc/plugins.dox
  9. 7
      doc/snippets/CMakeLists.txt
  10. 95
      doc/snippets/MagnumShaderTools.cpp
  11. 27
      modules/FindMagnum.cmake
  12. 4
      src/Magnum/CMakeLists.txt
  13. 429
      src/Magnum/ShaderTools/AbstractConverter.cpp
  14. 651
      src/Magnum/ShaderTools/AbstractConverter.h
  15. 102
      src/Magnum/ShaderTools/CMakeLists.txt
  16. 40
      src/Magnum/ShaderTools/ShaderTools.h
  17. 1572
      src/Magnum/ShaderTools/Test/AbstractConverterTest.cpp
  18. 41
      src/Magnum/ShaderTools/Test/CMakeLists.txt
  19. 27
      src/Magnum/ShaderTools/Test/configure.h.cmake
  20. 1
      src/Magnum/ShaderTools/Test/file.dat
  21. 27
      src/Magnum/ShaderTools/configure.h.cmake
  22. 48
      src/Magnum/ShaderTools/visibility.h
  23. 5
      src/Magnum/Text/AbstractFont.h
  24. 5
      src/Magnum/Trade/AbstractImporter.h

8
CMakeLists.txt

@ -95,6 +95,7 @@ option(WITH_DEBUGTOOLS "Build DebugTools library" ON)
cmake_dependent_option(WITH_MESHTOOLS "Build MeshTools library" ON "NOT WITH_OBJIMPORTER;NOT WITH_SCENECONVERTER" ON)
option(WITH_SCENEGRAPH "Build SceneGraph library" ON)
option(WITH_SHADERS "Build Shaders library" ON)
option(WITH_SHADERTOOLS "Build ShaderTools library" ON)
cmake_dependent_option(WITH_TEXT "Build Text library" ON "NOT WITH_FONTCONVERTER;NOT WITH_MAGNUMFONT;NOT WITH_MAGNUMFONTCONVERTER" ON)
cmake_dependent_option(WITH_TEXTURETOOLS "Build TextureTools library" ON "NOT WITH_TEXT;NOT WITH_DISTANCEFIELDCONVERTER" ON)
cmake_dependent_option(WITH_TRADE "Build Trade library" ON "NOT WITH_MESHTOOLS;NOT WITH_PRIMITIVES;NOT WITH_IMAGECONVERTER;NOT WITH_ANYIMAGEIMPORTER;NOT WITH_ANYIMAGECONVERTER;NOT WITH_ANYSCENEIMPORTER;NOT WITH_OBJIMPORTER;NOT WITH_TGAIMAGECONVERTER;NOT WITH_TGAIMPORTER" ON)
@ -362,6 +363,10 @@ set(MAGNUM_PLUGINS_SCENECONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBU
set(MAGNUM_PLUGINS_SCENECONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/sceneconverters)
set(MAGNUM_PLUGINS_SCENECONVERTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/sceneconverters)
set(MAGNUM_PLUGINS_SCENECONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/sceneconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/audioimporters)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/audioimporters)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/audioimporters)
@ -396,6 +401,7 @@ set(MAGNUM_PLUGINS_DIR ""
# Plugin directories. Set only if the above are non-empty. otherwise empty as
# well.
if(MAGNUM_PLUGINS_DIR)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DIR ${MAGNUM_PLUGINS_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_FONT_DIR ${MAGNUM_PLUGINS_DIR}/fonts)
set(MAGNUM_PLUGINS_FONTCONVERTER_DIR ${MAGNUM_PLUGINS_DIR}/fontconverters)
set(MAGNUM_PLUGINS_IMAGECONVERTER_DIR ${MAGNUM_PLUGINS_DIR}/imageconverters)
@ -404,6 +410,7 @@ if(MAGNUM_PLUGINS_DIR)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_DIR ${MAGNUM_PLUGINS_DIR}/audioimporters)
endif()
if(MAGNUM_PLUGINS_DEBUG_DIR)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_DIR ${MAGNUM_PLUGINS_DEBUG_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_FONT_DEBUG_DIR ${MAGNUM_PLUGINS_DEBUG_DIR}/fonts)
set(MAGNUM_PLUGINS_FONTCONVERTER_DEBUG_DIR ${MAGNUM_PLUGINS_DEBUG_DIR}/fontconverters)
set(MAGNUM_PLUGINS_IMAGECONVERTER_DEBUG_DIR ${MAGNUM_PLUGINS_DEBUG_DIR}/imageconverters)
@ -413,6 +420,7 @@ if(MAGNUM_PLUGINS_DEBUG_DIR)
set(MAGNUM_PLUGINS_AUDIOIMPORTER_DEBUG_DIR ${MAGNUM_PLUGINS_DEBUG_DIR}/audioimporters)
endif()
if(MAGNUM_PLUGINS_RELEASE_DIR)
set(MAGNUM_PLUGINS_SHADERCONVERTER_RELEASE_DIR ${MAGNUM_PLUGINS_RELEASE_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_FONTCONVERTER_RELEASE_DIR ${MAGNUM_PLUGINS_RELEASE_DIR}/fontconverters)
set(MAGNUM_PLUGINS_IMAGECONVERTER_RELEASE_DIR ${MAGNUM_PLUGINS_RELEASE_DIR}/imageconverters)
set(MAGNUM_PLUGINS_IMPORTER_RELEASE_DIR ${MAGNUM_PLUGINS_RELEASE_DIR}/importers)

1
doc/building.dox

@ -490,6 +490,7 @@ specify which parts will be built and which not:
- `WITH_SCENEGRAPH` --- Build the @ref SceneGraph library
- `WITH_SHADERS` --- Build the @ref Shaders library. Enables also building of
the GL library.
- `WITH_SHADERTOOLS` --- Build the @ref ShaderTools library
- `WITH_TEXT` --- Build the @ref Text library. Enables also building of
the TextureTools library.
- `WITH_TEXTURETOOLS` --- Build the @ref TextureTools library. Enabled

6
doc/changelog.dox

@ -87,6 +87,12 @@ See also:
- Added @ref Shaders::Phong::setLightSpecularColors() for better control over
speculat highlights
@subsubsection changelog-latest-new-shadertools ShaderTools library
- New @ref ShaderTools library that provides a
@ref ShaderTools::AbstractConverter plugin interface for shader validation,
conversion, compilation and optimization
@subsubsection changelog-latest-new-scenegraph SceneGraph library
- Added @ref SceneGraph::Object::move()

1
doc/cmake.dox

@ -197,6 +197,7 @@ the components. The optional components are:
- `Primitives` --- @ref Primitives library
- `SceneGraph` --- @ref SceneGraph library
- `Shaders` --- @ref Shaders library
- `ShaderTools` --- @ref ShaderTools library
- `Text` --- @ref Text library
- `TextureTools` --- @ref TextureTools library
- `Trade` --- @ref Trade library

1
doc/compilation-speedup.dox

@ -62,6 +62,7 @@ available, each namespace has its own:
- @ref Magnum/OvrIntegration/OvrIntegration.h
- @ref Magnum/Platform/Platform.h
- @ref Magnum/SceneGraph/SceneGraph.h
- @ref Magnum/ShaderTools/ShaderTools.h
- @ref Magnum/Shaders/Shaders.h
- @ref Magnum/Text/Text.h
- @ref Magnum/Trade/Trade.h

2
doc/custom-buildsystems-order.dot

@ -45,6 +45,7 @@ digraph "Magnum library dependency order" {
MagnumPrimitives [label="Magnum\nPrimitives" class="m-info"]
MagnumSceneGraph [label="Magnum\nSceneGraph" class="m-info"]
MagnumShaders [label="Magnum\nShaders" class="m-info"]
MagnumShaderTools [label="Magnum\nShaderTools" class="m-info"]
MagnumText [label="Magnum\nText" class="m-info"]
MagnumTextureTools [label="Magnum\nTextureTools" class="m-info"]
MagnumTrade [label="Magnum\nTrade" class="m-info"]
@ -85,6 +86,7 @@ digraph "Magnum library dependency order" {
MagnumSceneGraph -> Magnum
MagnumShaders -> MagnumGL
MagnumShaderTools -> Magnum
MagnumText -> MagnumTextureTools
MagnumText -> MagnumGL [style=dotted]

26
doc/namespaces.dox

@ -493,6 +493,32 @@ See @ref building, @ref cmake and @ref shaders for more information.
*/
/** @dir Magnum/ShaderTools
* @brief Namespace @ref Magnum::ShaderTools
* @m_since_latest
*/
/** @namespace Magnum::ShaderTools
@brief Shader tools
@m_since_latest
Shader validation, conversion, compilation and reflection.
This library is built if `WITH_SHADERTOOLS` is enabled when building Magnum. To
use this library with CMake, request the `ShaderTools` component of the
`Magnum` package and link to the `Magnum::ShaderTools` target:
@code{.cmake}
find_package(Magnum REQUIRED ShaderTools)
# ...
target_link_libraries(your-app PRIVATE Magnum::ShaderTools)
@endcode
Additional plugins and utilities are built separately. See particular
`*Converter` class documentation, @ref building, @ref building-plugins,
@ref cmake, @ref cmake-plugins and @ref plugins for more information.
*/
/** @dir Magnum/Text
* @brief Namespace @ref Magnum::Text
*/

3
doc/plugins.dox

@ -75,6 +75,9 @@ of given type. Magnum provides these plugin interfaces:
- @ref Audio::AbstractImporter --- importers for audio formats. See
`*Importer` classes in the @ref Audio namespace for available audio
importer plugins.
- @ref ShaderTools::AbstractConverter --- shader conversion, compilation,
optimization and validation. See `*Converter` classes in the
@ref ShaderTools namespace for available shader converter plugins.
@section plugins-loading Loading and instantiating plugins

7
doc/snippets/CMakeLists.txt

@ -100,6 +100,13 @@ if(WITH_MESHTOOLS)
set_target_properties(snippets-MagnumMeshTools PROPERTIES FOLDER "Magnum/doc/snippets")
endif()
if(WITH_SHADERTOOLS)
add_library(snippets-MagnumShaderTools STATIC
MagnumShaderTools.cpp)
target_link_libraries(snippets-MagnumShaderTools PRIVATE MagnumShaderTools)
set_target_properties(snippets-MagnumShaderTools PROPERTIES FOLDER "Magnum/doc/snippets")
endif()
if(WITH_TRADE)
add_library(snippets-MagnumTrade STATIC
plugins.cpp

95
doc/snippets/MagnumShaderTools.cpp

@ -0,0 +1,95 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <unordered_map>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Utility/Resource.h>
#include "Magnum/FileCallback.h"
#include "Magnum/ShaderTools/AbstractConverter.h"
#define DOXYGEN_IGNORE(...) __VA_ARGS__
using namespace Magnum;
int main() {
{
Containers::Pointer<ShaderTools::AbstractConverter> converter;
Containers::Array<const char> extract(const std::string&, const std::string&);
/* [AbstractConverter-usage-callbacks] */
struct Data {
std::unordered_map<std::string,
Containers::Array<const char>> files;
} data;
converter->setInputFileCallback([](const std::string& filename,
InputFileCallbackPolicy policy, Data& data)
-> Containers::Optional<Containers::ArrayView<const char>>
{
auto found = data.files.find(filename);
/* Discard the loaded file, if not needed anymore */
if(policy == InputFileCallbackPolicy::Close) {
if(found != data.files.end()) data.files.erase(found);
return {};
}
/* Extract from an archive if not there yet */
if(found == data.files.end()) found = data.files.emplace(
filename, extract("shaders.zip", filename)).first;
return Containers::arrayView(found->second);
}, data);
/* extracted from a ZIP */
auto result = converter->validateFile(ShaderTools::Stage::Fragment, "ssao.frag");
/* [AbstractConverter-usage-callbacks] */
}
{
Containers::Pointer<ShaderTools::AbstractConverter> converter;
/* [AbstractConverter-setInputFileCallback] */
converter->setInputFileCallback([](const std::string& filename,
InputFileCallbackPolicy, void*) {
Utility::Resource rs("data");
return Containers::optional(rs.getRaw(filename));
});
/* [AbstractConverter-setInputFileCallback] */
}
{
Containers::Pointer<ShaderTools::AbstractConverter> converter;
/* [AbstractConverter-setInputFileCallback-template] */
const Utility::Resource rs{"data"};
converter->setInputFileCallback([](const std::string& filename,
InputFileCallbackPolicy, const Utility::Resource& rs) {
return Containers::optional(rs.getRaw(filename));
}, rs);
/* [AbstractConverter-setInputFileCallback-template] */
}
}

27
modules/FindMagnum.cmake

@ -64,6 +64,7 @@
# Primitives - Primitives library
# SceneGraph - SceneGraph library
# Shaders - Shaders library
# ShaderTools - ShaderTools library
# Text - Text library
# TextureTools - TextureTools library
# Trade - Trade library
@ -164,6 +165,10 @@
# installation directory
# MAGNUM_PLUGINS_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Plugin library
# installation directory
# MAGNUM_PLUGINS_SHADERCONVERTER_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Shader
# converter plugin binary installation directory
# MAGNUM_PLUGINS_SHADERCONVERTER_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Shader
# converter plugin library installation directory
# MAGNUM_PLUGINS_FONT_[DEBUG|RELEASE]_BINARY_INSTALL_DIR - Font plugin binary
# installation directory
# MAGNUM_PLUGINS_FONT_[DEBUG|RELEASE]_LIBRARY_INSTALL_DIR - Font plugin
@ -224,7 +229,7 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
# Unrolling the transitive dependencies here so this doesn't need to be
# after resolving inter-component dependencies. Listing also all plugins.
if(_component MATCHES "^(Audio|DebugTools|MeshTools|Primitives|Text|TextureTools|Trade|.+Importer|.+ImageConverter|.+Font)$")
if(_component MATCHES "^(Audio|DebugTools|MeshTools|Primitives|ShaderTools|Text|TextureTools|Trade|.+Importer|.+ImageConverter|.+Font|.+ShaderConverter)$")
set(_MAGNUM_${_COMPONENT}_CORRADE_DEPENDENCIES PluginManager)
endif()
@ -355,8 +360,8 @@ endif()
# Component distinction (listing them explicitly to avoid mistakes with finding
# components from other repositories)
set(_MAGNUM_LIBRARY_COMPONENT_LIST
Audio DebugTools GL MeshTools Primitives SceneGraph Shaders Text
TextureTools Trade Vk
Audio DebugTools GL MeshTools Primitives SceneGraph Shaders ShaderTools
Text TextureTools Trade Vk
AndroidApplication EmscriptenApplication GlfwApplication GlxApplication
Sdl2Application XEglApplication WindowlessCglApplication
WindowlessEglApplication WindowlessGlxApplication WindowlessIosApplication
@ -470,6 +475,8 @@ set(_MAGNUM_ObjImporter_DEPENDENCIES MeshTools) # and below
foreach(_component ${_MAGNUM_PLUGIN_COMPONENT_LIST})
if(_component MATCHES ".+AudioImporter")
list(APPEND _MAGNUM_${_component}_DEPENDENCIES Audio)
elseif(_component MATCHES ".+ShaderConverter")
list(APPEND _MAGNUM_${_component}_DEPENDENCIES ShaderTools)
elseif(_component MATCHES ".+(Importer|ImageConverter|SceneConverter)")
list(APPEND _MAGNUM_${_component}_DEPENDENCIES Trade)
elseif(_component MATCHES ".+(Font|FontConverter)")
@ -549,6 +556,10 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
string(REPLACE "AudioImporter" "Importer" _MAGNUM_${_COMPONENT}_HEADER_NAME "${_component}")
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES ${_MAGNUM_${_COMPONENT}_HEADER_NAME}.h)
# ShaderConverter plugin specific name suffixes
elseif(_component MATCHES ".+ShaderConverter$")
set(_MAGNUM_${_COMPONENT}_PATH_SUFFIX shaderconverters)
# Importer plugin specific name suffixes
elseif(_component MATCHES ".+Importer$")
set(_MAGNUM_${_COMPONENT}_PATH_SUFFIX importers)
@ -862,6 +873,12 @@ foreach(_component ${Magnum_FIND_COMPONENTS})
set(_MAGNUM_${_COMPONENT}_INCLUDE_PATH_NAMES Cube.h)
# No special setup for SceneGraph library
# ShaderTools library
elseif(_component STREQUAL ShaderTools)
set_property(TARGET Magnum::${_component} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES Corrade::PluginManager)
# No special setup for Shaders library
# Text library
@ -1116,6 +1133,10 @@ set(MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum-
set(MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum-d)
set(MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_BINARY_INSTALL_DIR}/magnum)
set(MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_LIBRARY_INSTALL_DIR}/magnum)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_RELEASE_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_LIBRARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_SHADERCONVERTER_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/shaderconverters)
set(MAGNUM_PLUGINS_FONT_DEBUG_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_BINARY_INSTALL_DIR}/fonts)
set(MAGNUM_PLUGINS_FONT_DEBUG_LIBRARY_INSTALL_DIR ${MAGNUM_PLUGINS_DEBUG_LIBRARY_INSTALL_DIR}/fonts)
set(MAGNUM_PLUGINS_FONT_RELEASE_BINARY_INSTALL_DIR ${MAGNUM_PLUGINS_RELEASE_BINARY_INSTALL_DIR}/fonts)

4
src/Magnum/CMakeLists.txt

@ -215,6 +215,10 @@ if(WITH_SHADERS)
add_subdirectory(Shaders)
endif()
if(WITH_SHADERTOOLS)
add_subdirectory(ShaderTools)
endif()
if(WITH_TEXT)
add_subdirectory(Text)
endif()

429
src/Magnum/ShaderTools/AbstractConverter.cpp

@ -0,0 +1,429 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "AbstractConverter.h"
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/EnumSet.hpp>
#include <Corrade/Containers/Optional.h>
#include <Corrade/Containers/String.h>
#include <Corrade/Containers/StringStl.h>
#include <Corrade/Utility/DebugStl.h>
#include <Corrade/Utility/Directory.h>
#include "Magnum/FileCallback.h"
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
#include "Magnum/ShaderTools/configure.h"
#endif
namespace Magnum { namespace ShaderTools {
std::string AbstractConverter::pluginInterface() {
return
/* [interface] */
"cz.mosra.magnum.ShaderTools.AbstractConverter/0.1"
/* [interface] */
;
}
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
std::vector<std::string> AbstractConverter::pluginSearchPaths() {
return PluginManager::implicitPluginSearchPaths(
#ifndef MAGNUM_BUILD_STATIC
Utility::Directory::libraryLocation(&pluginInterface),
#else
{},
#endif
#ifdef CORRADE_IS_DEBUG_BUILD
MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_DIR,
#else
MAGNUM_PLUGINS_SHADERCONVERTER_DIR,
#endif
#ifdef CORRADE_IS_DEBUG_BUILD
"magnum-d/"
#else
"magnum/"
#endif
"shaderconverters");
}
#endif
AbstractConverter::AbstractConverter() = default;
AbstractConverter::AbstractConverter(PluginManager::Manager<AbstractConverter>& manager): PluginManager::AbstractManagingPlugin<AbstractConverter>{manager} {}
AbstractConverter::AbstractConverter(PluginManager::AbstractManager& manager, const std::string& plugin): PluginManager::AbstractManagingPlugin<AbstractConverter>{manager, plugin} {}
ConverterFeatures AbstractConverter::features() const {
const ConverterFeatures features = doFeatures();
CORRADE_ASSERT(features & ~ConverterFeature::InputFileCallback, "ShaderTools::AbstractConverter::features(): implementation reported no features", {});
return features;
}
void AbstractConverter::setFlags(const ConverterFlags flags) {
_flags = flags;
doSetFlags(flags);
}
void AbstractConverter::doSetFlags(ConverterFlags) {}
void AbstractConverter::setInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* const userData) {
/* Clearing the *File bits as those are present in *Data as well and thus
this would pass even if only file conversion/validation is supported,
which is wrong */
CORRADE_ASSERT(features() & (ConverterFeature::InputFileCallback|ConverterFeature::ValidateData|ConverterFeature::ConvertData) & ~(ConverterFeature::ValidateFile|ConverterFeature::ConvertFile),
"ShaderTools::AbstractConverter::setInputFileCallback(): converter supports neither loading from data nor via callbacks, callbacks can't be used", );
_inputFileCallback = callback;
_inputFileCallbackUserData = userData;
doSetInputFileCallback(callback, userData);
}
void AbstractConverter::doSetInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*), void*) {}
std::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", {});
/* 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(),
"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>) {
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) {
CORRADE_ASSERT(features() & (ConverterFeature::ValidateFile|ConverterFeature::ValidateData),
"ShaderTools::AbstractConverter::validateFile(): feature not supported", {});
std::pair<bool, Containers::String> out;
/* If input file callbacks are not set or the converter supports handling
them directly, call into the implementation */
if(!_inputFileCallback || (doFeatures() & ConverterFeature::InputFileCallback)) {
out = doValidateFile(stage, filename);
/* Otherwise, if validating data is supported, use the callback and pass
the data through to validateData(). Mark the file as ready to be closed
once validating is finished. */
} else if(doFeatures() & ConverterFeature::ValidateData) {
/* This needs to be duplicated here and in the doValidateFile()
implementation in order to support both following cases:
- plugins that don't support InputFileCallback but have their own
doValidateFile() implementation (callback needs to be used here,
because the base doValidateFile() implementation might never get
called)
- plugins that support InputFileCallback but want to delegate the
actual file loading to the default implementation (callback used
in the base doValidateFile() implementation, because this branch
is never taken in that case) */
const Containers::Optional<Containers::ArrayView<const char>> data = _inputFileCallback(filename, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData);
if(!data) {
Error{} << "ShaderTools::AbstractConverter::validateFile(): cannot open file" << filename;
return {};
}
out = doValidateData(stage, *data);
_inputFileCallback(filename, InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
/* 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(),
"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) {
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
validateFile(), see the comment there for details. */
if(_inputFileCallback) {
const Containers::Optional<Containers::ArrayView<const char>> data = _inputFileCallback(filename, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData);
if(!data) {
Error{} << "ShaderTools::AbstractConverter::validateFile(): cannot open file" << filename;
return {};
}
std::pair<bool, Containers::String> out = doValidateData(stage, *data);
_inputFileCallback(filename, InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
return out;
/* Otherwise open the file directly */
} else {
if(!Utility::Directory::exists(filename)) {
Error() << "ShaderTools::AbstractConverter::validateFile(): cannot open file" << filename;
return {};
}
return doValidateData(stage, Utility::Directory::read(filename));
}
}
Containers::Array<char> AbstractConverter::convertDataToData(const Stage stage, const Containers::ArrayView<const void> data) {
CORRADE_ASSERT(features() >= ConverterFeature::ConvertData,
"ShaderTools::AbstractConverter::convertDataToData(): feature not supported", {});
/* Cast to a non-void type for more convenience */
Containers::Array<char> out = doConvertDataToData(stage, Containers::arrayCast<const char>(data));
CORRADE_ASSERT(!out.deleter(),
"ShaderTools::AbstractConverter::convertDataToData(): implementation is not allowed to use a custom Array deleter", {});
return out;
}
Containers::Array<char> AbstractConverter::doConvertDataToData(Stage, Containers::ArrayView<const char>) {
CORRADE_ASSERT_UNREACHABLE("ShaderTools::AbstractConverter::convertDataToData(): feature advertised but not implemented", {});
}
bool AbstractConverter::convertDataToFile(const Stage stage, const Containers::ArrayView<const void> data, const Containers::StringView to) {
CORRADE_ASSERT(features() >= ConverterFeature::ConvertData,
"ShaderTools::AbstractConverter::convertDataToFile(): feature not supported", {});
/** @todo this needs expansion once output callbacks are supported as well */
/* Cast to a non-void type for more convenience */
Containers::Array<char> out = doConvertDataToData(stage, Containers::arrayCast<const char>(data));
if(!out) return false;
if(!Utility::Directory::write(to, out)) {
Error{} << "ShaderTools::AbstractConverter::convertDataToFile(): cannot write to file" << to;
return false;
}
return true;
}
Containers::Array<char> AbstractConverter::convertDataToDataUsingInputFileCallbacks(const char* const prefix, const Stage stage, const Containers::StringView from) {
const Containers::Optional<Containers::ArrayView<const char>> data = _inputFileCallback(from, InputFileCallbackPolicy::LoadTemporary, _inputFileCallbackUserData);
if(!data) {
Error{} << prefix << "cannot open file" << from;
return {};
}
Containers::Array<char> out = doConvertDataToData(stage, *data);
_inputFileCallback(from, InputFileCallbackPolicy::Close, _inputFileCallbackUserData);
return out;
}
bool AbstractConverter::convertFileToFile(const Stage stage, const Containers::StringView from, const Containers::StringView to) {
CORRADE_ASSERT(features() & (ConverterFeature::ConvertFile|ConverterFeature::ConvertData),
"ShaderTools::AbstractConverter::convertFileToFile(): feature not supported", {});
/** @todo this needs expansion once output callbacks are supported as well */
/* If input file callbacks are not set or the converter supports handling
them directly, call into the implementation */
if(!_inputFileCallback || (doFeatures() & ConverterFeature::InputFileCallback)) {
return doConvertFileToFile(stage, from, to);
/* Otherwise, if converting data is supported, use the callback and pass
the data through to convertDataToData(). Mark the file as ready to be
closed once conversion is finished. */
} else if(doFeatures() & ConverterFeature::ConvertData) {
/* This needs to be duplicated here and in the doConvertFileToFile()
implementation in order to support both following cases:
- plugins that don't support InputFileCallback but have their own
doConvertFileToFile() implementation (callback needs to be used
here, because the base doConvertFileToFile() implementation might
never get called)
- plugins that support InputFileCallback but want to delegate the
actual file loading to the default implementation (callback used
in the base doConvertFileToFile() implementation, because this
branch is never taken in that case) */
Containers::Array<char> out = convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToFile():", stage, from);
if(!out) return false;
if(!Utility::Directory::write(to, out)) {
Error{} << "ShaderTools::AbstractConverter::convertFileToFile(): cannot write to file" << to;
return false;
}
return true;
/* Shouldn't get here, the assert is fired already in setFileCallback() */
} else CORRADE_INTERNAL_ASSERT_UNREACHABLE(); /* LCOV_EXCL_LINE */
}
bool AbstractConverter::doConvertFileToFile(const Stage stage, const Containers::StringView from, const Containers::StringView to) {
CORRADE_ASSERT(features() >= ConverterFeature::ConvertData, "ShaderTools::AbstractConverter::convertFileToFile(): feature advertised but not implemented", {});
/** @todo this needs expansion once output callbacks are supported as well */
Containers::Array<char> out;
/* If callbacks are set, use them. This is the same implementation as in
convertFileToFile(), see the comment there for details. */
if(_inputFileCallback) {
out = convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToFile():", stage, from);
/* Otherwise open the file directly */
} else {
if(!Utility::Directory::exists(from)) {
Error() << "ShaderTools::AbstractConverter::convertFileToFile(): cannot open file" << from;
return {};
}
out = doConvertDataToData(stage, Utility::Directory::read(from));
}
if(!out) return false;
if(!Utility::Directory::write(to, out)) {
Error{} << "ShaderTools::AbstractConverter::convertFileToFile(): cannot write to file" << to;
return false;
}
return true;
}
Containers::Array<char> AbstractConverter::convertFileToData(const Stage stage, const Containers::StringView from) {
CORRADE_ASSERT(features() >= ConverterFeature::ConvertData,
"ShaderTools::AbstractConverter::convertFileToData(): feature not supported", {});
Containers::Array<char> out;
/* If input file callbacks are not set or the converter supports handling
them directly, call into the implementation */
if(!_inputFileCallback || (doFeatures() & ConverterFeature::InputFileCallback)) {
out = doConvertFileToData(stage, from);
/* Otherwise use the callback and pass the data through to
convertDataToData(). Mark the file as ready to be closed once conversion
is finished. */
} else {
/* This needs to be duplicated here and in the doConvertFileToData()
implementation in order to support both following cases:
- plugins that don't support InputFileCallback but have their own
doConvertFileToData() implementation (callback needs to be used
here, because the base doConvertFileToData() implementation might
never get called)
- plugins that support InputFileCallback but want to delegate the
actual file loading to the default implementation (callback used
in the base doConvertFileToData() implementation, because this
branch is never taken in that case) */
out = convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToData():", stage, from);
}
CORRADE_ASSERT(!out.deleter(),
"ShaderTools::AbstractConverter::convertFileToData(): implementation is not allowed to use a custom Array deleter", {});
return out;
}
Containers::Array<char> AbstractConverter::doConvertFileToData(const Stage stage, const Containers::StringView from) {
/* If callbacks are set, use them. This is the same implementation as in
convertFileToFile(), see the comment there for details. */
if(_inputFileCallback) {
return convertDataToDataUsingInputFileCallbacks("ShaderTools::AbstractConverter::convertFileToData():", stage, from);
/* Otherwise open the file directly */
} else {
if(!Utility::Directory::exists(from)) {
Error() << "ShaderTools::AbstractConverter::convertFileToData(): cannot open file" << from;
return {};
}
return doConvertDataToData(stage, Utility::Directory::read(from));
}
}
Debug& operator<<(Debug& debug, const ConverterFeature value) {
debug << "ShaderTools::ConverterFeature" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(v) case ConverterFeature::v: return debug << "::" #v;
_c(ValidateData)
_c(ValidateFile)
_c(ConvertData)
_c(ConvertFile)
_c(InputFileCallback)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, const ConverterFeatures value) {
return Containers::enumSetDebugOutput(debug, value, "ShaderTools::ConverterFeatures{}", {
ConverterFeature::ValidateData,
/* Implied by ValidateData, has to be after */
ConverterFeature::ValidateFile,
ConverterFeature::ConvertData,
/* Implied by ConvertData, has to be after */
ConverterFeature::ConvertFile,
ConverterFeature::InputFileCallback});
}
Debug& operator<<(Debug& debug, const ConverterFlag value) {
debug << "ShaderTools::ConverterFlag" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(v) case ConverterFlag::v: return debug << "::" #v;
_c(Verbose)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
Debug& operator<<(Debug& debug, const ConverterFlags value) {
return Containers::enumSetDebugOutput(debug, value, "ShaderTools::ConverterFlags{}", {
ConverterFlag::Verbose});
}
Debug& operator<<(Debug& debug, const Stage value) {
debug << "ShaderTools::Stage" << Debug::nospace;
switch(value) {
/* LCOV_EXCL_START */
#define _c(v) case Stage::v: return debug << "::" #v;
_c(Unspecified)
_c(Vertex)
_c(Fragment)
_c(Geometry)
_c(TessellationControl)
_c(TessellationEvaluation)
_c(Compute)
_c(RayGeneration)
_c(RayAnyHit)
_c(RayClosestHit)
_c(RayMiss)
_c(RayIntersection)
_c(RayCallable)
_c(MeshTask)
_c(Mesh)
#undef _c
/* LCOV_EXCL_STOP */
}
return debug << "(" << Debug::nospace << reinterpret_cast<void*>(UnsignedByte(value)) << Debug::nospace << ")";
}
}}

651
src/Magnum/ShaderTools/AbstractConverter.h

@ -0,0 +1,651 @@
#ifndef Magnum_ShaderTools_AbstractConverter_h
#define Magnum_ShaderTools_AbstractConverter_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class @ref Magnum::ShaderTools::AbstractConverter, enum @ref Magnum::ShaderTools::ConverterFeature, @ref Magnum::ShaderTools::ConverterFlag, @ref Magnum::ShaderTools::Stage, enum set @ref Magnum::ShaderTools::ConverterFeatures, @ref Magnum::ShaderTools::ConverterFlags
* @m_since_latest
*/
#include <Corrade/Containers/EnumSet.h>
#include <Corrade/PluginManager/AbstractManagingPlugin.h>
#include "Magnum/Magnum.h"
#include "Magnum/ShaderTools/visibility.h"
namespace Magnum { namespace ShaderTools {
/**
@brief Features supported by a shader converter
@m_since_latest
@see @ref ConverterFeatures, @ref AbstractConverter::features()
*/
enum class ConverterFeature: UnsignedInt {
/**
* Validate shader file with @ref AbstractConverter::validateFile()
*/
ValidateFile = 1 << 0,
/**
* Validate shader data with @ref AbstractConverter::validateData().
* Implies @ref ConverterFeature::ValidateData.
*/
ValidateData = ValidateFile|(1 << 1),
/**
* Convert shader file to a file with @ref AbstractConverter::convertFileToFile()
*/
ConvertFile = 1 << 2,
/**
* Convert shader data to data with
* @ref AbstractConverter::convertDataToData() or any of the other
* @ref AbstractConverter::convertDataToFile(),
* @ref AbstractConverter::convertFileToData() combinations. Implies
* @ref ConverterFeature::ConvertFile.
*/
ConvertData = ConvertFile|(1 << 3),
/**
* Specifying input file callbacks for additional files referenced from the
* main file using @ref AbstractConverter::setInputFileCallback(). If the
* converter doesn't expose this feature, the format is either single-file
* or input file callbacks are not supported.
*
* See @ref ShaderTools-AbstractConverter-usage-callbacks and particular
* converter documentation for more information.
*/
InputFileCallback = 1 << 4
};
/**
@brief Features supported by a shader converter
@m_since_latest
@see @ref AbstractConverter::features()
*/
typedef Containers::EnumSet<ConverterFeature> ConverterFeatures;
CORRADE_ENUMSET_OPERATORS(ConverterFeatures)
/**
@debugoperatorenum{ConverterFeature}
@m_since_latest
*/
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFeature value);
/**
@debugoperatorenum{ConverterFeatures}
@m_since_latest
*/
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFeatures value);
/**
@brief Shader converter flag
@m_since_latest
@see @ref ConverterFlags, @ref AbstractConverter::setFlags()
*/
enum class ConverterFlag: UnsignedInt {
/**
* Print verbose diagnostic. By default the converter only prints warnings
* and errors.
*/
Verbose = 1 << 0
};
/**
@brief Shader converter flags
@m_since_latest
@see @ref AbstractConverter::setFlags()
*/
typedef Containers::EnumSet<ConverterFlag> ConverterFlags;
CORRADE_ENUMSET_OPERATORS(ConverterFlags)
/**
@debugoperatorenum{ConverterFlag}
@m_since_latest
*/
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFlag value);
/**
@debugoperatorenum{ConverterFlags}
@m_since_latest
*/
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, ConverterFlags value);
/**
@brief Shader stage
@m_since_latest
@see @ref AbstractConverter
*/
enum class Stage: UnsignedInt {
/**
* Unspecified stage. When used in the
* @ref AbstractConverter::validateFile(),
* @ref AbstractConverter::convertFileToFile() "convertFileToFile()",
* @ref AbstractConverter::convertFileToData() "convertFileToData()" APIs,
* particular plugins may attempt to detect the stage from filename, the
* shader stage might also be encoded directly in certain formats. Leaving
* the stage unspecified might limit validation and conversion
* capabilities, see documentation of a particular converter for concrete
* behavior.
*
* This value is guaranteed to be @cpp 0 @ce, which means you're encouraged
* to simply use @cpp {} @ce in function calls and elsewhere.
*/
Unspecified = 0,
Vertex, /**< Vertex stage */
Fragment, /**< Fragment stage */
Geometry, /**< Geometry stage */
TessellationControl, /**< Tessellation control stage */
TessellationEvaluation, /**< Tessellation evaluation stage */
Compute, /**< Compute stage */
RayGeneration, /**< Ray generation stage */
RayAnyHit, /**< Ray any hit stage */
RayClosestHit, /**< Ray closest hit stage */
RayMiss, /**< Ray miss stage */
RayIntersection, /**< Ray intersection stage */
RayCallable, /**< Ray callable stage */
MeshTask, /**< Mesh task stage */
Mesh /**< Mesh stage */
};
/**
@debugoperatorenum{Stage}
@m_since_latest
*/
MAGNUM_SHADERTOOLS_EXPORT Debug& operator<<(Debug& debug, Stage value);
/**
@brief Base for shader converter plugins
@m_since_latest
Provides functionality for validating and converting shader code between
different representations or performing optimizations and other operations on
them. See @ref plugins for more information and `*ShaderConverter` classes in
the @ref ShaderTools namespace for available scene converter plugins.
@section ShaderTools-AbstractConverter-usage Usage
Shader converters are most commonly implemented as plugins. Depending on
exposed @ref features(), a plugin can support shader validation, conversion or
linking.
@subsection ShaderTools-AbstractConverter-usage-validation Shader validation
@subsection ShaderTools-AbstractConverter-usage-conversion Shader conversion
@subsection ShaderTools-AbstractConverter-usage-callbacks Loading shaders from memory, using file callbacks
Besides loading shaders directly from the filesystem using @ref validateFile()
/ @ref convertFileToFile() like shown above, it's possible to use
@ref validateData(), @ref convertDataToData() and variants to load data from
memory. Note that the particular converter implementation has to support
@ref ConverterFeature::ValidateData / @ref ConverterFeature::ConvertData for
this method to work.
Textual shader sources sometimes @cpp #include @ce other sources and in that
case you may want to intercept those references and load them in a custom way
as well. For converters that advertise support for this with
@ref ConverterFeature::InputFileCallback this is done by specifying an input
file callback using @ref setInputFileCallback(). The callback gets a filename,
@ref InputFileCallbackPolicy and an user pointer as parameters; returns a
non-owning view on the loaded data or a
@ref Corrade::Containers::NullOpt "Containers::NullOpt" to indicate the file
loading failed. For example, validating a shader from compiled-in resources
could look like below. Note that the input file callback affects
@ref validateFile() / @ref convertFileToFile() / @ref convertFileToData() as
well --- you don't have to load the top-level file manually and pass it to
@ref validateData() / @ref convertDataToData(), any converter supporting the
callback feature handles that correctly.
@snippet MagnumShaderTools.cpp AbstractConverter-usage-callbacks
For converters that don't support @ref ConverterFeature::InputFileCallback
directly, the base @ref validateFile() / @ref convertFileToFile() /
@ref convertFileToData() implementations will use the file callback to pass
the loaded data through to @ref validateData() / @ref convertDataToData(), in
case the converter supports at least @ref ConverterFeature::ValidateData
/ @ref ConverterFeature::ConvertData. If the converter supports none of
@ref ConverterFeature::InputFileCallback, @ref ConverterFeature::ValidateData
or @ref ConverterFeature::ConvertData, @ref setInputFileCallback() doesn't
allow the callbacks to be set.
The input file callback signature is the same for
@ref ShaderTools::AbstractConverter, @ref Trade::AbstractImporter and
@ref Text::AbstractFont to allow code reuse.
@section ShaderTools-AbstractConverter-data-dependency Data dependency
The instances returned from various functions *by design* have no dependency on
the importer instance and neither on the dynamic plugin module. In other words,
you don't need to keep the importer instance (or the plugin manager instance)
around in order to have the returned data valid --- all returned
@ref Corrade::Containers::String and @ref Corrade::Containers::Array instances
are only allowed to have default deleters and this is to avoid potential
dangling function pointer calls when destructing such instances after the
plugin module has been unloaded.
@section ShaderTools-AbstractConverter-subclassing Subclassing
The plugin needs to implement the @ref doFeatures() function and one or more of
@ref doValidateData(), @ref doValidateFile(), @ref doConvertDataToData(),
@ref doConvertFileToData(), or @ref doConvertFileToFile() functions based on
what features are supported.
You don't need to do most of the redundant sanity checks, these things are
checked by the implementation:
- The function @ref doValidateData() is called only if
@ref ConverterFeature::ValidateData is supported.
- The function @ref doValidateFile() is called only if
@ref ConverterFeature::ValidateFile is supported.
- Functions @ref doConvertDataToData() and @ref doConvertFileToData() are
called only if @ref ConverterFeature::ConvertData is supported.
- The function @ref doConvertFileToFile() is called only if
@ref ConverterFeature::ConvertFile is supported.
@m_class{m-block m-warning}
@par Dangling function pointers on plugin unload
As @ref ShaderTools-AbstractConverter-data-dependency "mentioned above",
@ref Corrade::Containers::String and @ref Corrade::Containers::Array
instances returned from plugin implementations are not allowed to use
anything else than the default deleter, otherwise this could cause dangling
function pointer call on array destruction if the plugin gets unloaded
before the array is destroyed. This is asserted by the base implementation
on return.
*/
class MAGNUM_SHADERTOOLS_EXPORT AbstractConverter: public PluginManager::AbstractManagingPlugin<AbstractConverter> {
public:
/**
* @brief Plugin interface
*
* @snippet Magnum/ShaderTools/AbstractConverter.cpp interface
*/
static std::string pluginInterface();
#ifndef CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT
/**
* @brief Plugin search paths
*
* Looks into `magnum/shaderconverters/` or `magnum-d/shaderconverters/`
* next to the dynamic @ref ShaderTools library, next to the executable
* and elsewhere according to the rules documented in
* @ref Corrade::PluginManager::implicitPluginSearchPaths(). The search
* directory can be also hardcoded using the `MAGNUM_PLUGINS_DIR` CMake
* variables, see @ref building for more information.
*
* Not defined on platforms without
* @ref CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT "dynamic plugin support".
*/
static std::vector<std::string> pluginSearchPaths();
#endif
/** @brief Default constructor */
explicit AbstractConverter();
/** @brief Constructor with access to plugin manager */
explicit AbstractConverter(PluginManager::Manager<AbstractConverter>& manager);
/** @brief Plugin manager constructor */
explicit AbstractConverter(PluginManager::AbstractManager& manager, const std::string& plugin);
/** @brief Features supported by this converter */
ConverterFeatures features() const;
/** @brief Converter flags */
ConverterFlags flags() const { return _flags; }
/**
* @brief Set converter flags
*
* Some flags can be set only if the converter supports particular
* features, see documentation of each @ref ConverterFlag for more
* information. By default no flags are set.
*/
void setFlags(ConverterFlags flags);
/**
* @brief Input file callback function
*
* @see @ref ShaderTools-AbstractConverter-usage-callbacks
*/
auto inputFileCallback() const -> Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, void*) { return _inputFileCallback; }
/**
* @brief Input file callback user data
*
* @see @ref ShaderTools-AbstractConverter-usage-callbacks
*/
void* inputFileCallbackUserData() const { return _inputFileCallbackUserData; }
/**
* @brief Set input file callback
*
* In case the converter supports @ref ConverterFeature::InputFileCallback,
* files opened through @ref validateFile(), @ref convertFileToData()
* and @ref convertFileToFile() will be loaded through the provided
* callback. Besides that, all external files referenced by the
* top-level file will be loaded through the callback function as well,
* usually on demand. The callback function gets a filename,
* @ref InputFileCallbackPolicy and the @p userData pointer as input
* and returns a non-owning view on the loaded data as output or a
* @ref Corrade::Containers::NullOpt if loading failed --- because
* empty files might also be valid in some circumstances,
* @cpp nullptr @ce can't be used to indicate a failure.
*
* In case the converter doesn't support
* @ref ConverterFeature::InputFileCallback but supports at least
* @ref ConverterFeature::ValidateData /
* @ref ConverterFeature::ConvertData, a file opened through
* @ref validateFile(), @ref convertFileToData() or
* @ref convertFileToFile() will be internally loaded through the
* provided callback and then passed to @ref validateData() or
* @ref convertDataToData(). First the file is loaded with
* @ref InputFileCallbackPolicy::LoadTemporary passed to the callback,
* then the returned memory view is passed to @ref validateData() /
* @ref convertDataToData() (sidestepping the potential
* @ref validateFile() / @ref convertFileToFile() implementation of
* that particular converter) and after that the callback is called
* again with @ref InputFileCallbackPolicy::Close. In case you need a
* different behavior, use @ref validateData() /
* @ref convertDataToData() directly.
*
* In case @p callback is @cpp nullptr @ce, the current callback (if
* any) is reset. This function expects that the converter supports
* either @ref ConverterFeature::InputFileCallback or at least one of
* @ref ConverterFeature::ValidateData,
* @ref ConverterFeature::ConvertData. If a converter supports neither,
* callbacks can't be used.
*
* Following is an example of setting up an input file callback for
* fetching compiled-in resources from @ref Corrade::Utility::Resource.
* See the overload below for a more convenient type-safe way to pass
* the user data pointer.
*
* @snippet MagnumShaderTools.cpp AbstractConverter-setInputFileCallback
*
* @see @ref ShaderTools-AbstractConverter-usage-callbacks
*/
void setInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* userData = nullptr);
/**
* @brief Set file opening callback
*
* Equivalent to calling the above with a lambda wrapper that casts
* @cpp void* @ce back to @cpp T* @ce and dereferences it in order to
* pass it to @p callback. Example usage --- this reuses an existing
* @ref Corrade::Utility::Resource instance to avoid a potentially slow
* resource group lookup every time:
*
* @snippet MagnumShaderTools.cpp AbstractConverter-setInputFileCallback-template
*
* @see @ref ShaderTools-AbstractConverter-usage-callbacks
*/
#ifdef DOXYGEN_GENERATING_OUTPUT
template<class T> void setInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, T&), T& userData);
#else
/* Otherwise the user would be forced to use the + operator to convert
a lambda to a function pointer and (besides being weird and
annoying) it's also not portable because it doesn't work on MSVC
2015 and older versions of MSVC 2017. */
template<class Callback, class T> void setInputFileCallback(Callback callback, T& userData);
#endif
/**
* @brief Validate a shader
*
* Available only if @ref ConverterFeature::ValidateData is
* supported. Returns
*
* - @cpp true @ce and an empty string if validation passes without
* warnings,
* - @cpp true @ce and a non-empty string if validation passes with
* warnings, and
* - @cpp false @ce if validation doesn't pass. If an external error
* occurs (for example a referenced file not being found), it may
* also happen that the returned string is empty and a message is
* printed to error output instead.
*
* @see @ref features(), @ref validateFile()
*/
std::pair<bool, Containers::String> validateData(Stage stage, Containers::ArrayView<const void> data);
/**
* @brief Validate a shader
*
* Available only if @ref ConverterFeature::ValidateFile or
* @ref ConverterFeature::ValidateData is supported. Returns
*
* - @cpp true @ce and an empty string if validation passes without
* warnings,
* - @cpp true @ce and a non-empty string if validation passes with
* warnings, and
* - @cpp false @ce if validation doesn't pass. If an external error
* occurs (for example when a file cannot be read), it may also
* happen that the returned string is empty and a message is
* printed to error output instead.
*
* @see @ref features(), @ref validateData()
*/
std::pair<bool, Containers::String> validateFile(Stage stage, Containers::StringView filename);
/**
* @brief Convert shader data to a data
*
* Available only if @ref ConverterFeature::ConvertData is supported.
* On failure the function prints an error message and returns
* @cpp nullptr @ce.
* @see @ref features(), @ref convertDataToFile(),
* @ref convertFileToData(), @ref convertFileToFile()
*/
Containers::Array<char> convertDataToData(Stage stage, Containers::ArrayView<const void> data);
/**
* @brief Convert shader data to a file
*
* Available only if @ref ConverterFeature::ConvertData is supported.
* Returns @cpp true @ce on success, prints an error message and
* returns @cpp false @ce otherwise.
* @see @ref features(), @ref convertDataToData(),
* @ref convertFileToData(), @ref convertFileToFile()
*/
bool convertDataToFile(Stage stage, Containers::ArrayView<const void> data, Containers::StringView to);
/**
* @brief Convert shader file to a file
*
* Available only if @ref ConverterFeature::ConvertFile or
* @ref ConverterFeature::ConvertData is supported. Returns
* @cpp true @ce on success, prints an error message and returns
* @cpp false @ce otherwise.
* @see @ref features(), @ref convertFileToData(),
* @ref convertDataToData(), @ref convertDataToFile()
*/
bool convertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to);
/**
* @brief Convert shader data to a file
*
* Available only if @ref ConverterFeature::ConvertData is supported.
* On failure the function prints an error message and returns
* @cpp nullptr @ce.
* @see @ref features(), @ref convertFileToFile(),
* @ref convertDataToFile(), @ref convertDataToData()
*/
Containers::Array<char> convertFileToData(Stage stage, const Containers::StringView from);
protected:
/**
* @brief Implementation for @ref validateFile()
*
* If @ref ConverterFeature::ValidateData is supported, default
* implementation opens the file and calls @ref doValidateData() with
* its contents. It is allowed to call this function from your
* @ref doValidateFile() implementation --- in particular, this
* implementation will also correctly handle callbacks set through
* @ref setInputFileCallback().
*
* This function is not called when file callbacks are set through
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback
* is not supported --- instead, file is loaded though the callback and
* data passed through to @ref doValidateData().
*/
virtual std::pair<bool, Containers::String> doValidateFile(Stage stage, Containers::StringView filename);
/**
* @brief Implementation for @ref convertFileToFile()
*
* If @ref ConverterFeature::ConvertData is supported, default
* implementation opens the file and calls @ref doConvertDataToData()
* with its contents, then saving the output to a file. It is allowed
* to call this function from your @ref doConvertFileToFile()
* implementation --- in particular, this implementation will also
* correctly handle callbacks set through @ref setInputFileCallback().
*
* This function is not called when file callbacks are set through
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback
* is not supported --- instead, file is loaded though the callback and
* data passed through to @ref doConvertDataToData().
*/
virtual bool doConvertFileToFile(Stage stage, Containers::StringView from, Containers::StringView to);
/**
* @brief Implementation for @ref convertFileToData()
*
* Default implementation opens the file and calls
* @ref doConvertDataToData() with its contents --- you only need to
* implement this if you need to do extra work with file inputs. It is
* allowed to call this function from your @ref doConvertFileToData()
* implementation --- in particular, this implementation will also
* correctly handle callbacks set through @ref setInputFileCallback().
*
* This function is not called when file callbacks are set through
* @ref setInputFileCallback() and @ref ConverterFeature::InputFileCallback
* is not supported --- instead, file is loaded though the callback and
* data passed through to @ref doConvertDataToData().
*/
virtual Containers::Array<char> doConvertFileToData(Stage stage, Containers::StringView from);
private:
/**
* @brief Implementation for @ref features()
*
* Has to be implemented always, the implementation is expected to
* support at least one feature.
*/
virtual ConverterFeatures doFeatures() const = 0;
/**
* @brief Implementation for @ref setFlags()
*
* Useful when the converter needs to modify some internal state on
* flag setup. Default implementation does nothing and this
* function doesn't need to be implemented --- the flags are available
* through @ref flags().
*
* To reduce the amount of error checking on user side, this function
* isn't expected to fail --- if a flag combination is invalid /
* unsuported, error reporting should be delayed to various conversion
* functions, where the user is expected to do error handling anyway.
*/
virtual void doSetFlags(ConverterFlags flags);
/**
* @brief Implementation for @ref setInputFileCallback()
*
* Useful when the converter needs to modify some internal state on
* callback setup. Default implementation does nothing and this
* function doesn't need to be implemented --- the callback function
* and user data pointer are available through @ref inputFileCallback()
* and @ref inputFileCallbackUserData().
*/
virtual void doSetInputFileCallback(Containers::Optional<Containers::ArrayView<const char>>(*callback)(const std::string&, InputFileCallbackPolicy, void*), void* userData);
/**
* @brief Implementation for @ref validateData()
*
* Has to be implemented if @ref ConverterFeature::ValidateData
* is supported. While @ref validateData() uses a @cpp void @ce view in
* order to accept any type, this function gets it cast to
* @cpp char @ce for more convenience.
*/
virtual std::pair<bool, Containers::String> doValidateData(Stage stage, Containers::ArrayView<const char> data);
/* Used by convertFileToFile(), doConvertFileToFile(),
convertFileToData() and doConvertFileToData() */
MAGNUM_SHADERTOOLS_LOCAL Containers::Array<char> convertDataToDataUsingInputFileCallbacks(const char* prefix, const Stage stage, Containers::StringView from);
/**
* @brief Implementation for @ref convertDataToData()
*
* Has to be implemented if @ref ConverterFeature::ConvertData is
* supported. While @ref convertDataToData() uses a @cpp void @ce view
* in order to accept any type, this function gets it cast to
* @cpp char @ce for more convenience.
*/
virtual Containers::Array<char> doConvertDataToData(Stage stage, Containers::ArrayView<const char> data);
ConverterFlags _flags;
Containers::Optional<Containers::ArrayView<const char>>(*_inputFileCallback)(const std::string&, InputFileCallbackPolicy, void*){};
void* _inputFileCallbackUserData{};
/* Used by the templated version only */
struct FileCallbackTemplate {
void(*callback)();
const void* userData;
/* GCC 4.8 complains loudly about missing initializers otherwise */
} _inputFileCallbackTemplate{nullptr, nullptr};
};
#ifndef DOXYGEN_GENERATING_OUTPUT
template<class Callback, class T> void AbstractConverter::setInputFileCallback(Callback callback, T& userData) {
/* Don't try to wrap a null function pointer. Need to cast first because
MSVC (even 2017) can't apply ! to a lambda. Ugh. */
const auto callbackPtr = static_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&)>(callback);
if(!callbackPtr) return setInputFileCallback(nullptr);
_inputFileCallbackTemplate = { reinterpret_cast<void(*)()>(callbackPtr), static_cast<const void*>(&userData) };
setInputFileCallback([](const std::string& filename, const InputFileCallbackPolicy flags, void* const userData) {
auto& s = *reinterpret_cast<FileCallbackTemplate*>(userData);
return reinterpret_cast<Containers::Optional<Containers::ArrayView<const char>>(*)(const std::string&, InputFileCallbackPolicy, T&)>(s.callback)(filename, flags, *static_cast<T*>(const_cast<void*>(s.userData)));
}, &_inputFileCallbackTemplate);
}
#endif
}}
#endif

102
src/Magnum/ShaderTools/CMakeLists.txt

@ -0,0 +1,102 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020 Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
find_package(Corrade REQUIRED PluginManager)
# Files shared between main library and unit test library
set(MagnumShaderTools_SRCS )
# Files compiled with different flags for main library and unit test library
set(MagnumShaderTools_GracefulAssert_SRCS
AbstractConverter.cpp)
set(MagnumShaderTools_HEADERS
AbstractConverter.h
ShaderTools.h
visibility.h)
if(NOT CORRADE_PLUGINMANAGER_NO_DYNAMIC_PLUGIN_SUPPORT)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/configure.h)
endif()
# # Objects shared between main and test library
# add_library(MagnumShaderToolsObjects OBJECT
# ${MagnumShaderTools_SRCS}
# ${MagnumShaderTools_HEADERS})
# target_include_directories(MagnumShaderToolsObjects PUBLIC $<TARGET_PROPERTY:Magnum,INTERFACE_INCLUDE_DIRECTORIES>)
# if(NOT BUILD_STATIC)
# target_compile_definitions(MagnumShaderToolsObjects PRIVATE "MagnumShaderToolsObjects_EXPORTS")
# endif()
# if(NOT BUILD_STATIC OR BUILD_STATIC_PIC)
# set_target_properties(MagnumShaderToolsObjects PROPERTIES POSITION_INDEPENDENT_CODE ON)
# endif()
# set_target_properties(MagnumShaderToolsObjects PROPERTIES FOLDER "Magnum/ShaderTools")
# Main ShaderTools library
add_library(MagnumShaderTools ${SHARED_OR_STATIC}
# $<TARGET_OBJECTS:MagnumShaderToolsObjects>
${MagnumShaderTools_GracefulAssert_SRCS})
set_target_properties(MagnumShaderTools PROPERTIES
DEBUG_POSTFIX "-d"
FOLDER "Magnum/ShaderTools")
if(NOT BUILD_STATIC)
set_target_properties(MagnumShaderTools PROPERTIES VERSION ${MAGNUM_LIBRARY_VERSION} SOVERSION ${MAGNUM_LIBRARY_SOVERSION})
elseif(BUILD_STATIC_PIC)
set_target_properties(MagnumShaderTools PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
target_link_libraries(MagnumShaderTools PUBLIC
Magnum
Corrade::PluginManager)
install(TARGETS MagnumShaderTools
RUNTIME DESTINATION ${MAGNUM_BINARY_INSTALL_DIR}
LIBRARY DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR}
ARCHIVE DESTINATION ${MAGNUM_LIBRARY_INSTALL_DIR})
install(FILES ${MagnumShaderTools_HEADERS} DESTINATION ${MAGNUM_INCLUDE_INSTALL_DIR}/ShaderTools)
if(BUILD_TESTS)
# Library with graceful assert for testing
add_library(MagnumShaderToolsTestLib ${SHARED_OR_STATIC}
# $<TARGET_OBJECTS:MagnumShaderToolsObjects>
${MagnumShaderTools_GracefulAssert_SRCS})
set_target_properties(MagnumShaderToolsTestLib PROPERTIES
DEBUG_POSTFIX "-d"
FOLDER "Magnum/ShaderTools")
target_compile_definitions(MagnumShaderToolsTestLib PRIVATE
"CORRADE_GRACEFUL_ASSERT" "MagnumShaderTools_EXPORTS")
if(BUILD_STATIC_PIC)
set_target_properties(MagnumShaderToolsTestLib PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
target_link_libraries(MagnumShaderToolsTestLib PUBLIC
Magnum
Corrade::PluginManager)
add_subdirectory(Test)
endif()
# Magnum ShaderTools target alias for superprojects
add_library(Magnum::ShaderTools ALIAS MagnumShaderTools)

40
src/Magnum/ShaderTools/ShaderTools.h

@ -0,0 +1,40 @@
#ifndef Magnum_Trade_ShaderTools_h
#define Magnum_Trade_ShaderTools_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Forward declarations for the @ref Magnum::ShaderTools namespace
*/
namespace Magnum { namespace Trade {
#ifndef DOXYGEN_GENERATING_OUTPUT
class AbstractConverter;
#endif
}}
#endif

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

File diff suppressed because it is too large Load Diff

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

@ -0,0 +1,41 @@
#
# This file is part of Magnum.
#
# Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
# 2020 Vladimír Vondruš <mosra@centrum.cz>
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
if(CORRADE_TARGET_EMSCRIPTEN OR CORRADE_TARGET_ANDROID)
set(SHADERTOOLS_TEST_DIR ".")
set(SHADERTOOLS_TEST_OUTPUT_DIR "./write")
else()
set(SHADERTOOLS_TEST_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(SHADERTOOLS_TEST_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/configure.h.cmake
${CMAKE_CURRENT_BINARY_DIR}/configure.h)
corrade_add_test(ShaderToolsAbstractConverterTest AbstractConverterTest.cpp
LIBRARIES MagnumShaderToolsTestLib
FILES file.dat)
target_include_directories(ShaderToolsAbstractConverterTest PRIVATE ${CMAKE_CURRENT_BINARY_DIR})

27
src/Magnum/ShaderTools/Test/configure.h.cmake

@ -0,0 +1,27 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#define SHADERTOOLS_TEST_DIR "${SHADERTOOLS_TEST_DIR}"
#define SHADERTOOLS_TEST_OUTPUT_DIR "${SHADERTOOLS_TEST_OUTPUT_DIR}"

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

@ -0,0 +1 @@
SPIRV

27
src/Magnum/ShaderTools/configure.h.cmake

@ -0,0 +1,27 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#define MAGNUM_PLUGINS_SHADERCONVERTER_DIR "${MAGNUM_PLUGINS_SHADERCONVERTER_DIR}"
#define MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_DIR "${MAGNUM_PLUGINS_SHADERCONVERTER_DEBUG_DIR}"

48
src/Magnum/ShaderTools/visibility.h

@ -0,0 +1,48 @@
#ifndef Magnum_ShaderTools_visibility_h
#define Magnum_ShaderTools_visibility_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
2020 Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <Corrade/Utility/VisibilityMacros.h>
#include "Magnum/configure.h"
#ifndef DOXYGEN_GENERATING_OUTPUT
#ifndef MAGNUM_BUILD_STATIC
#if defined(MagnumShaderTools_EXPORTS) || defined(MagnumShaderToolsObjects_EXPORTS)
#define MAGNUM_SHADERTOOLS_EXPORT CORRADE_VISIBILITY_EXPORT
#else
#define MAGNUM_SHADERTOOLS_EXPORT CORRADE_VISIBILITY_IMPORT
#endif
#else
#define MAGNUM_SHADERTOOLS_EXPORT CORRADE_VISIBILITY_STATIC
#endif
#define MAGNUM_SHADERTOOLS_LOCAL CORRADE_VISIBILITY_LOCAL
#else
#define MAGNUM_SHADERTOOLS_EXPORT
#define MAGNUM_SHADERTOOLS_LOCAL
#endif
#endif

5
src/Magnum/Text/AbstractFont.h

@ -145,8 +145,9 @@ loaded data through to @ref openData(), in case the importer supports at least
@ref FontFeature::FileCallback nor @ref FontFeature::OpenData,
@ref setFileCallback() doesn't allow the callbacks to be set.
The input file callback signature is the same for @ref Text::AbstractFont and
@ref Trade::AbstractImporter to allow code reuse.
The input file callback signature is the same for @ref Text::AbstractFont,
@ref ShaderTools::AbstractConverter and @ref Trade::AbstractImporter to allow
code reuse.
@section Text-AbstractFont-subclassing Subclassing

5
src/Magnum/Trade/AbstractImporter.h

@ -188,8 +188,9 @@ loaded data through to @ref openData(), in case the importer supports at least
@ref ImporterFeature::FileCallback nor @ref ImporterFeature::OpenData,
@ref setFileCallback() doesn't allow the callbacks to be set.
The input file callback signature is the same for @ref Trade::AbstractImporter
and @ref Text::AbstractFont to allow code reuse.
The input file callback signature is the same for @ref Trade::AbstractImporter,
@ref ShaderTools::AbstractConverter and @ref Text::AbstractFont to allow code
reuse.
@subsection Trade-AbstractImporter-usage-state Internal importer state

Loading…
Cancel
Save